update
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
"use client";
|
||||
import { useEffect } from 'react';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import AboutBanner from "@/components/pages/about/AboutBanner";
|
||||
import AboutServiceComponent from "@/components/pages/about/AboutService";
|
||||
@@ -7,7 +8,15 @@ import AboutScrollProgressButton from "@/components/pages/about/AboutScrollProgr
|
||||
import AboutInitAnimations from "@/components/pages/about/AboutInitAnimations";
|
||||
import AboutStarter from "@/components/pages/about/AboutStarter";
|
||||
|
||||
// Note: Since this is a client component, we'll set metadata via useEffect
|
||||
const page = () => {
|
||||
useEffect(() => {
|
||||
document.title = "About Us - Enterprise Software Development Company | GNX Soft";
|
||||
const metaDescription = document.querySelector('meta[name="description"]');
|
||||
if (metaDescription) {
|
||||
metaDescription.setAttribute('content', 'Learn about GNX Soft - a leading enterprise software development company with expertise in custom software, data replication, AI business intelligence, and comprehensive IT solutions.');
|
||||
}
|
||||
}, []);
|
||||
return (
|
||||
<div className="enterprise-about-page">
|
||||
<Header />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Metadata } from 'next';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import CareerBanner from "@/components/pages/career/CareerBanner";
|
||||
import OpenPosition from "@/components/pages/career/OpenPosition";
|
||||
@@ -5,6 +6,21 @@ import Thrive from "@/components/pages/career/Thrive";
|
||||
import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import CareerScrollProgressButton from "@/components/pages/career/CareerScrollProgressButton";
|
||||
import CareerInitAnimations from "@/components/pages/career/CareerInitAnimations";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Careers - Join Our Team",
|
||||
description: "Explore career opportunities at GNX Soft. Join our team of talented professionals working on cutting-edge enterprise software solutions. View open positions and apply today.",
|
||||
keywords: [
|
||||
"Careers",
|
||||
"Job Openings",
|
||||
"Software Development Jobs",
|
||||
"Join Our Team",
|
||||
"Tech Careers",
|
||||
"Employment Opportunities",
|
||||
],
|
||||
url: "/career",
|
||||
});
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
import { Metadata } from 'next';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import CaseItems from "@/components/pages/case-study/CaseItems";
|
||||
import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import CaseStudyScrollProgressButton from "@/components/pages/case-study/CaseStudyScrollProgressButton";
|
||||
import CaseStudyInitAnimations from "@/components/pages/case-study/CaseStudyInitAnimations";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Case Studies - Success Stories & Client Projects",
|
||||
description: "Explore our case studies showcasing successful enterprise software development projects, client success stories, and real-world implementations of our technology solutions.",
|
||||
keywords: [
|
||||
"Case Studies",
|
||||
"Success Stories",
|
||||
"Client Projects",
|
||||
"Software Development Portfolio",
|
||||
"Enterprise Solutions Examples",
|
||||
"Client Testimonials",
|
||||
],
|
||||
url: "/case-study",
|
||||
});
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,23 @@
|
||||
import { Metadata } from 'next';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import ContactSection from "@/components/pages/contact/ContactSection";
|
||||
import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import ContactScrollProgressButton from "@/components/pages/contact/ContactScrollProgressButton";
|
||||
import ContactInitAnimations from "@/components/pages/contact/ContactInitAnimations";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Contact Us - Get in Touch with Our Team",
|
||||
description: "Contact GNX Soft for enterprise software development solutions. Get a free consultation, discuss your project requirements, or request a quote for our services.",
|
||||
keywords: [
|
||||
"Contact GNX Soft",
|
||||
"Software Development Quote",
|
||||
"Enterprise Solutions Consultation",
|
||||
"Custom Software Inquiry",
|
||||
"Get in Touch",
|
||||
],
|
||||
url: "/contact-us",
|
||||
});
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
import { Metadata } from 'next';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import BlogItems from "@/components/pages/blog/BlogItems";
|
||||
import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import BlogScrollProgressButton from "@/components/pages/blog/BlogScrollProgressButton";
|
||||
import BlogInitAnimations from "@/components/pages/blog/BlogInitAnimations";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Insights & Blog - Technology Trends & Best Practices",
|
||||
description: "Stay updated with the latest insights on enterprise software development, technology trends, best practices, and industry news from GNX Soft's expert team.",
|
||||
keywords: [
|
||||
"Technology Blog",
|
||||
"Software Development Insights",
|
||||
"Tech Trends",
|
||||
"Enterprise Software Blog",
|
||||
"Development Best Practices",
|
||||
"Industry News",
|
||||
],
|
||||
url: "/insights",
|
||||
});
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
@@ -4,6 +4,8 @@ import "@/public/styles/main.scss";
|
||||
import { CookieConsentProvider } from "@/components/shared/layout/CookieConsentContext";
|
||||
import { CookieConsent } from "@/components/shared/layout/CookieConsent";
|
||||
import LayoutWrapper from "@/components/shared/layout/LayoutWrapper";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
import { OrganizationSchema, WebsiteSchema, LocalBusinessSchema } from "@/components/shared/seo/StructuredData";
|
||||
|
||||
const montserrat = Montserrat({
|
||||
subsets: ["latin"],
|
||||
@@ -37,26 +39,22 @@ const inter = Inter({
|
||||
],
|
||||
});
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "EnterpriseSoft Solutions | Enterprise Software Development & IT Solutions",
|
||||
description: "Leading enterprise software development company providing custom solutions, system integrations, and digital transformation services for Fortune 500 companies",
|
||||
// Enhanced SEO metadata for root layout
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Enterprise Software Development & IT Solutions",
|
||||
description: "Leading enterprise software development company specializing in custom software, data replication, incident management, AI business intelligence, and comprehensive system integrations for modern businesses.",
|
||||
keywords: [
|
||||
"Enterprise Software",
|
||||
"Custom Development",
|
||||
"System Integration",
|
||||
"Digital Transformation",
|
||||
"Enterprise Solutions",
|
||||
"Software Consulting",
|
||||
"API Development",
|
||||
"Cloud Migration",
|
||||
"Enterprise Software Development",
|
||||
"Custom Software Solutions",
|
||||
"Data Replication Services",
|
||||
"Incident Management SaaS",
|
||||
"AI Business Intelligence",
|
||||
"Backend Engineering",
|
||||
"Frontend Engineering",
|
||||
"Systems Integration",
|
||||
],
|
||||
authors: [
|
||||
{
|
||||
name: "EnterpriseSoft Solutions",
|
||||
url: "https://enterprisesoft.com",
|
||||
},
|
||||
],
|
||||
};
|
||||
url: "/",
|
||||
});
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
@@ -76,14 +74,85 @@ export default function RootLayout({
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
{/* Content Protection Script */}
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function() {
|
||||
if (typeof window === 'undefined') return;
|
||||
|
||||
// Wait for DOM to be ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Disable right-click
|
||||
document.addEventListener('contextmenu', function(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Disable keyboard shortcuts
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Ctrl+C, Ctrl+X, Ctrl+S, Ctrl+A, Ctrl+P, Ctrl+U, Ctrl+I, Ctrl+J
|
||||
if ((e.ctrlKey || e.metaKey) && ['c','x','s','a','p','u','i','j','k'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
// F12
|
||||
if (e.key === 'F12' || e.keyCode === 123) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
// Ctrl+Shift+I, Ctrl+Shift+J, Ctrl+Shift+C
|
||||
if ((e.ctrlKey || e.metaKey) && e.shiftKey && ['I','J','C'].includes(e.key)) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Disable text selection
|
||||
document.addEventListener('selectstart', function(e) {
|
||||
if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Disable image dragging
|
||||
document.addEventListener('dragstart', function(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Disable copy/cut
|
||||
document.addEventListener('copy', function(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
document.addEventListener('cut', function(e) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Console warning
|
||||
console.log('%cSTOP!', 'color: red; font-size: 40px; font-weight: bold;');
|
||||
console.log('%c© GNX Soft - All Rights Reserved', 'font-size: 14px;');
|
||||
});
|
||||
})();
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
<body className={`${inter.variable} ${montserrat.variable}`} style={{ scrollBehavior: 'auto', overflow: 'auto' }}>
|
||||
<body className={`${inter.variable} ${montserrat.variable} content-protected`} style={{ scrollBehavior: 'auto', overflow: 'auto' }}>
|
||||
{/* Structured Data for SEO */}
|
||||
<OrganizationSchema />
|
||||
<WebsiteSchema />
|
||||
<LocalBusinessSchema />
|
||||
|
||||
<CookieConsentProvider
|
||||
config={{
|
||||
companyName: "EnterpriseSoft Solutions",
|
||||
privacyPolicyUrl: "/privacy-policy",
|
||||
cookiePolicyUrl: "/cookie-policy",
|
||||
dataControllerEmail: "privacy@enterprisesoft.com",
|
||||
companyName: "GNX Soft",
|
||||
privacyPolicyUrl: "/policy",
|
||||
cookiePolicyUrl: "/policy",
|
||||
dataControllerEmail: "privacy@gnxsoft.com",
|
||||
retentionPeriod: 365,
|
||||
enableAuditLog: true,
|
||||
enableDetailedSettings: true,
|
||||
|
||||
35
gnx-react/app/robots.ts
Normal file
35
gnx-react/app/robots.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { MetadataRoute } from 'next';
|
||||
|
||||
export default function robots(): MetadataRoute.Robots {
|
||||
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://gnxsoft.com';
|
||||
|
||||
return {
|
||||
rules: [
|
||||
{
|
||||
userAgent: '*',
|
||||
allow: '/',
|
||||
disallow: [
|
||||
'/api/',
|
||||
'/admin/',
|
||||
'/_next/',
|
||||
'/private/',
|
||||
'/*.json$',
|
||||
'/*?*',
|
||||
],
|
||||
},
|
||||
{
|
||||
userAgent: 'Googlebot',
|
||||
allow: '/',
|
||||
disallow: ['/api/', '/admin/', '/private/'],
|
||||
},
|
||||
{
|
||||
userAgent: 'Bingbot',
|
||||
allow: '/',
|
||||
disallow: ['/api/', '/admin/', '/private/'],
|
||||
},
|
||||
],
|
||||
sitemap: `${baseUrl}/sitemap.xml`,
|
||||
host: baseUrl,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import ServicesScrollProgressButton from "@/components/pages/services/ServicesScrollProgressButton";
|
||||
import ServicesInitAnimations from "@/components/pages/services/ServicesInitAnimations";
|
||||
import { serviceService, Service } from "@/lib/api/serviceService";
|
||||
import { generateServiceMetadata } from "@/lib/seo/metadata";
|
||||
import { ServiceSchema, BreadcrumbSchema } from "@/components/shared/seo/StructuredData";
|
||||
|
||||
interface ServicePageProps {
|
||||
params: Promise<{
|
||||
@@ -30,21 +32,13 @@ export async function generateStaticParams() {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate metadata for each service page
|
||||
// Generate enhanced metadata for each service page
|
||||
export async function generateMetadata({ params }: ServicePageProps) {
|
||||
try {
|
||||
const { slug } = await params;
|
||||
const service = await serviceService.getServiceBySlug(slug);
|
||||
|
||||
return {
|
||||
title: `${service.title} - GNX Services`,
|
||||
description: service.description,
|
||||
openGraph: {
|
||||
title: service.title,
|
||||
description: service.description,
|
||||
images: service.image_url ? [service.image_url] : [],
|
||||
},
|
||||
};
|
||||
return generateServiceMetadata(service);
|
||||
} catch (error) {
|
||||
return {
|
||||
title: 'Service Not Found - GNX',
|
||||
@@ -64,8 +58,19 @@ const ServicePage = async ({ params }: ServicePageProps) => {
|
||||
notFound();
|
||||
}
|
||||
|
||||
// Breadcrumb data for structured data
|
||||
const breadcrumbItems = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Services', url: '/services' },
|
||||
{ name: service.title, url: `/services/${service.slug}` },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="enterprise-app">
|
||||
{/* SEO Structured Data */}
|
||||
<ServiceSchema service={service} />
|
||||
<BreadcrumbSchema items={breadcrumbItems} />
|
||||
|
||||
<Header />
|
||||
<main className="enterprise-main">
|
||||
<ServiceDetailsBanner service={service} />
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
import { Metadata } from 'next';
|
||||
import Header from "@/components/shared/layout/header/Header";
|
||||
import ServicesBanner from "@/components/pages/services/ServicesBanner";
|
||||
import ServiceMain from "@/components/pages/services/ServiceMain";
|
||||
import Footer from "@/components/shared/layout/footer/Footer";
|
||||
import ServicesScrollProgressButton from "@/components/pages/services/ServicesScrollProgressButton";
|
||||
import ServicesInitAnimations from "@/components/pages/services/ServicesInitAnimations";
|
||||
import { generateMetadata as createMetadata } from "@/lib/seo/metadata";
|
||||
|
||||
export const metadata: Metadata = createMetadata({
|
||||
title: "Our Services - Enterprise Software Development",
|
||||
description: "Explore our comprehensive range of enterprise software development services including custom software, data replication, incident management, AI business intelligence, backend & frontend engineering, and systems integration.",
|
||||
keywords: [
|
||||
"Software Development Services",
|
||||
"Custom Software Development",
|
||||
"Data Replication",
|
||||
"Incident Management SaaS",
|
||||
"AI Business Intelligence",
|
||||
"Backend Engineering Services",
|
||||
"Frontend Development",
|
||||
"Systems Integration Services",
|
||||
],
|
||||
url: "/services",
|
||||
});
|
||||
|
||||
const page = () => {
|
||||
return (
|
||||
|
||||
137
gnx-react/app/sitemap.ts
Normal file
137
gnx-react/app/sitemap.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { MetadataRoute } from 'next';
|
||||
|
||||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://gnxsoft.com';
|
||||
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000/api';
|
||||
|
||||
// Static pages
|
||||
const staticPages: MetadataRoute.Sitemap = [
|
||||
{
|
||||
url: baseUrl,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'daily',
|
||||
priority: 1.0,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/about-us`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/services`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 0.9,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/case-study`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/insights`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'daily',
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/career`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'weekly',
|
||||
priority: 0.7,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/contact-us`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.8,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/support-center`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'monthly',
|
||||
priority: 0.7,
|
||||
},
|
||||
{
|
||||
url: `${baseUrl}/policy`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: 'yearly',
|
||||
priority: 0.5,
|
||||
},
|
||||
];
|
||||
|
||||
try {
|
||||
// Fetch dynamic services
|
||||
const servicesResponse = await fetch(`${apiUrl}/services/`, {
|
||||
next: { revalidate: 3600 }, // Revalidate every hour
|
||||
});
|
||||
|
||||
let servicePages: MetadataRoute.Sitemap = [];
|
||||
if (servicesResponse.ok) {
|
||||
const services = await servicesResponse.json();
|
||||
servicePages = services.map((service: any) => ({
|
||||
url: `${baseUrl}/services/${service.slug}`,
|
||||
lastModified: new Date(service.updated_at || service.created_at),
|
||||
changeFrequency: 'weekly' as const,
|
||||
priority: service.featured ? 0.9 : 0.7,
|
||||
}));
|
||||
}
|
||||
|
||||
// Fetch dynamic blog posts
|
||||
const blogResponse = await fetch(`${apiUrl}/blog/`, {
|
||||
next: { revalidate: 3600 },
|
||||
});
|
||||
|
||||
let blogPages: MetadataRoute.Sitemap = [];
|
||||
if (blogResponse.ok) {
|
||||
const posts = await blogResponse.json();
|
||||
blogPages = posts.map((post: any) => ({
|
||||
url: `${baseUrl}/insights/${post.slug}`,
|
||||
lastModified: new Date(post.updated_at || post.published_at),
|
||||
changeFrequency: 'weekly' as const,
|
||||
priority: 0.7,
|
||||
}));
|
||||
}
|
||||
|
||||
// Fetch dynamic case studies
|
||||
const caseStudiesResponse = await fetch(`${apiUrl}/case-studies/`, {
|
||||
next: { revalidate: 3600 },
|
||||
});
|
||||
|
||||
let caseStudyPages: MetadataRoute.Sitemap = [];
|
||||
if (caseStudiesResponse.ok) {
|
||||
const caseStudies = await caseStudiesResponse.json();
|
||||
caseStudyPages = caseStudies.map((study: any) => ({
|
||||
url: `${baseUrl}/case-study/${study.slug}`,
|
||||
lastModified: new Date(study.updated_at || study.created_at),
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.7,
|
||||
}));
|
||||
}
|
||||
|
||||
// Fetch dynamic career postings
|
||||
const careerResponse = await fetch(`${apiUrl}/career/positions/`, {
|
||||
next: { revalidate: 3600 },
|
||||
});
|
||||
|
||||
let careerPages: MetadataRoute.Sitemap = [];
|
||||
if (careerResponse.ok) {
|
||||
const positions = await careerResponse.json();
|
||||
careerPages = positions.map((position: any) => ({
|
||||
url: `${baseUrl}/career/${position.slug}`,
|
||||
lastModified: new Date(position.updated_at || position.created_at),
|
||||
changeFrequency: 'weekly' as const,
|
||||
priority: 0.6,
|
||||
}));
|
||||
}
|
||||
|
||||
return [...staticPages, ...servicePages, ...blogPages, ...caseStudyPages, ...careerPages];
|
||||
} catch (error) {
|
||||
console.error('Error generating sitemap:', error);
|
||||
// Return at least static pages if API fails
|
||||
return staticPages;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user