diff --git a/public-site/app/aktsii/page.jsx b/public-site/app/aktsii/page.jsx
index d0b6848..98634e2 100644
--- a/public-site/app/aktsii/page.jsx
+++ b/public-site/app/aktsii/page.jsx
@@ -7,6 +7,7 @@ export const metadata = {
title: 'Акции на IT-аутсорсинг, техподдержку и почтовые серверы',
description:
'Актуальные акции и специальные предложения TopSysOps: скидки на IT-аутсорсинг при годовом договоре, почтовый сервер под ключ, бот с ИИ-ассистентом.',
+ alternates: { canonical: '/aktsii' },
};
export default async function PromotionsPage() {
diff --git a/public-site/app/blog/[slug]/page.jsx b/public-site/app/blog/[slug]/page.jsx
index 96a5e97..4482727 100644
--- a/public-site/app/blog/[slug]/page.jsx
+++ b/public-site/app/blog/[slug]/page.jsx
@@ -17,6 +17,7 @@ export async function generateMetadata({ params }) {
return {
title: post.title,
description: post.excerpt || undefined,
+ alternates: { canonical: `/blog/${params.slug}` },
};
}
@@ -30,7 +31,7 @@ export default async function BlogPostPage({ params }) {
headline: post.title,
...(post.excerpt ? { description: post.excerpt } : {}),
...(post.published_at ? { datePublished: post.published_at } : {}),
- author: { '@type': 'Organization', name: 'TopSysOps' },
+ author: { '@id': `${process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru'}/#organization` },
};
return (
diff --git a/public-site/app/blog/page.jsx b/public-site/app/blog/page.jsx
index d15ab6e..a0784ab 100644
--- a/public-site/app/blog/page.jsx
+++ b/public-site/app/blog/page.jsx
@@ -9,6 +9,7 @@ import { serverApi } from '../../lib/serverApi.js';
export const metadata = {
title: 'Блог',
description: 'Заметки об IT-инфраструктуре, кибербезопасности и автоматизации от TopSysOps.',
+ alternates: { canonical: '/blog' },
};
function formatDate(iso) {
diff --git a/public-site/app/faq/page.jsx b/public-site/app/faq/page.jsx
index e02d345..4a9b67a 100644
--- a/public-site/app/faq/page.jsx
+++ b/public-site/app/faq/page.jsx
@@ -6,6 +6,7 @@ import { serverApi } from '../../lib/serverApi.js';
export const metadata = {
title: 'Частые вопросы об IT-аутсорсинге и услугах',
description: 'Ответы на частые вопросы об IT-аутсорсинге, техподдержке, оплате услуг и конфиденциальности данных TopSysOps.',
+ alternates: { canonical: '/faq' },
};
export default async function FaqPage() {
diff --git a/public-site/app/keysy/page.jsx b/public-site/app/keysy/page.jsx
index 3b5ee56..10511b7 100644
--- a/public-site/app/keysy/page.jsx
+++ b/public-site/app/keysy/page.jsx
@@ -7,6 +7,7 @@ export const metadata = {
title: 'Кейсы и портфолио — сетевая инфраструктура, ИИ, кибербезопасность',
description:
'Реализованные проекты TopSysOps: миграция сетевой инфраструктуры, внедрение ИИ-ассистента, аудит кибербезопасности финтех-проекта.',
+ alternates: { canonical: '/keysy' },
};
export default async function CasesPage() {
diff --git a/public-site/app/kontakty/page.jsx b/public-site/app/kontakty/page.jsx
index 94636b2..62b4c01 100644
--- a/public-site/app/kontakty/page.jsx
+++ b/public-site/app/kontakty/page.jsx
@@ -6,6 +6,7 @@ import { serverApi } from '../../lib/serverApi.js';
export const metadata = {
title: 'Контакты',
description: 'Контакты TopSysOps: адрес офиса в Санкт-Петербурге, телефон, email и режим работы. Работаем с клиентами по всей России.',
+ alternates: { canonical: '/kontakty' },
};
export default async function ContactPage() {
diff --git a/public-site/app/layout.jsx b/public-site/app/layout.jsx
index 0f427fd..bdfc125 100644
--- a/public-site/app/layout.jsx
+++ b/public-site/app/layout.jsx
@@ -2,6 +2,7 @@ import './globals.css';
import { ThemeProvider } from '../components/ThemeProvider.jsx';
import SupportChat from '../components/SupportChat.jsx';
import VisitTracker from '../components/VisitTracker.jsx';
+import { getOrganizationSchema } from '../lib/schema.js';
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru';
@@ -33,6 +34,8 @@ export default function RootLayout({ children }) {
{/* eslint-disable-next-line react/no-danger */}
+ {/* eslint-disable-next-line react/no-danger */}
+
{children}
diff --git a/public-site/app/o-kompanii/page.jsx b/public-site/app/o-kompanii/page.jsx
index f7da010..ffa2506 100644
--- a/public-site/app/o-kompanii/page.jsx
+++ b/public-site/app/o-kompanii/page.jsx
@@ -10,6 +10,7 @@ export const metadata = {
title: 'О компании',
description:
'TopSysOps — IT-аутсорсинг и техподдержка с 2023 года. Команда 20+ специалистов, штаб-квартира в Санкт-Петербурге, работаем с клиентами по всей России.',
+ alternates: { canonical: '/o-kompanii' },
};
const FACTS = [
@@ -47,6 +48,7 @@ export default async function AboutPage() {
const orgSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
+ '@id': `${process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru'}/#organization`,
name: 'TopSysOps',
url: process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru',
foundingDate: '2023',
diff --git a/public-site/app/otzyvy/page.jsx b/public-site/app/otzyvy/page.jsx
index f63786c..61e7c3a 100644
--- a/public-site/app/otzyvy/page.jsx
+++ b/public-site/app/otzyvy/page.jsx
@@ -6,6 +6,7 @@ import { serverApi } from '../../lib/serverApi.js';
export const metadata = {
title: 'Отзывы клиентов TopSysOps',
description: 'Отзывы клиентов об IT-аутсорсинге, техподдержке и других услугах TopSysOps. Оставьте свой отзыв.',
+ alternates: { canonical: '/otzyvy' },
};
export default async function ReviewsPage() {
diff --git a/public-site/app/page.jsx b/public-site/app/page.jsx
index f0e173c..2b09dd1 100644
--- a/public-site/app/page.jsx
+++ b/public-site/app/page.jsx
@@ -13,6 +13,10 @@ import Reveal from '../components/Reveal.jsx';
import SectionHeading from '../components/SectionHeading.jsx';
import { serverApi } from '../lib/serverApi.js';
+export const metadata = {
+ alternates: { canonical: '/' },
+};
+
export default async function HomePage() {
const [services, promotions, reviews, cases, contact] = await Promise.all([
serverApi.getServices(),
@@ -25,6 +29,7 @@ export default async function HomePage() {
const business = {
'@context': 'https://schema.org',
'@type': 'LocalBusiness',
+ '@id': `${process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru'}/#organization`,
name: 'TopSysOps',
url: process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru',
...(contact?.address ? { address: { '@type': 'PostalAddress', streetAddress: contact.address, addressCountry: 'RU' } } : {}),
diff --git a/public-site/app/uslugi/[slug]/page.jsx b/public-site/app/uslugi/[slug]/page.jsx
index 1d315fc..aec90e4 100644
--- a/public-site/app/uslugi/[slug]/page.jsx
+++ b/public-site/app/uslugi/[slug]/page.jsx
@@ -18,7 +18,11 @@ export async function generateMetadata({ params }) {
const category = await findCategory(params.slug);
if (!category) return { title: 'Услуга не найдена' };
const copy = getServiceLandingCopy(category);
- return { title: copy.metaTitle, description: copy.metaDescription };
+ return {
+ title: copy.metaTitle,
+ description: copy.metaDescription,
+ alternates: { canonical: `/uslugi/${category.slug}` },
+ };
}
export default async function ServiceLandingPage({ params }) {
@@ -33,7 +37,7 @@ export default async function ServiceLandingPage({ params }) {
'@type': 'Service',
name: copy.h1,
description: copy.metaDescription,
- provider: { '@type': 'Organization', name: 'TopSysOps' },
+ provider: { '@id': `${process.env.NEXT_PUBLIC_SITE_URL || 'https://top-sysops.ru'}/#organization` },
areaServed: 'RU',
};
diff --git a/public-site/app/uslugi/page.jsx b/public-site/app/uslugi/page.jsx
index dab320f..186233d 100644
--- a/public-site/app/uslugi/page.jsx
+++ b/public-site/app/uslugi/page.jsx
@@ -7,6 +7,7 @@ export const metadata = {
title: 'Услуги IT-аутсорсинга и техподдержки — прайс-лист',
description:
'IT-аутсорсинг, техподдержка, кибербезопасность, администрирование серверов и баз данных, сетевая инфраструктура, облачные решения, ИИ и автоматизация. Актуальные цены.',
+ alternates: { canonical: '/uslugi' },
};
export default async function ServicesPage() {
diff --git a/public-site/components/Header.jsx b/public-site/components/Header.jsx
index c57ffff..3be12cc 100644
--- a/public-site/components/Header.jsx
+++ b/public-site/components/Header.jsx
@@ -11,6 +11,8 @@ const NAV_ITEMS = [
{ href: '/uslugi', label: 'Услуги' },
{ href: '/aktsii', label: 'Акции' },
{ href: '/keysy', label: 'Кейсы' },
+ { href: '/otzyvy', label: 'Отзывы' },
+ { href: '/faq', label: 'FAQ' },
{ href: '/o-kompanii', label: 'О компании' },
{ href: '/blog', label: 'Блог' },
{ href: '/kontakty', label: 'Контакты' },
@@ -29,12 +31,12 @@ export default function Header() {
TopSysOps
-