From 30e1aea20b5f833755ef6a1018466076e6648eaf Mon Sep 17 00:00:00 2001 From: ogrechko Date: Tue, 25 Aug 2026 23:43:17 +0300 Subject: [PATCH] Fix SEO/UX audit gaps: canonical tags, org schema, nav, header claims Add canonical URLs and a sitewide Organization JSON-LD (linked via @id to page-specific LocalBusiness/Service/Article schemas), move FAQ and Reviews into the top nav, attach the 24/7 support claim to a tooltip on the header badge instead of leaving it unexplained, drop the unverifiable incidents_resolved stat from the hero terminal animation, and clean up the empty-reviews state instead of showing a thin placeholder. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013otXCiTZsxdZ4SJKZ9wUky --- public-site/app/aktsii/page.jsx | 1 + public-site/app/blog/[slug]/page.jsx | 3 ++- public-site/app/blog/page.jsx | 1 + public-site/app/faq/page.jsx | 1 + public-site/app/keysy/page.jsx | 1 + public-site/app/kontakty/page.jsx | 1 + public-site/app/layout.jsx | 3 +++ public-site/app/o-kompanii/page.jsx | 2 ++ public-site/app/otzyvy/page.jsx | 1 + public-site/app/page.jsx | 5 +++++ public-site/app/uslugi/[slug]/page.jsx | 8 ++++++-- public-site/app/uslugi/page.jsx | 1 + public-site/components/Header.jsx | 19 ++++++++++++------ public-site/components/sections/Hero.jsx | 2 +- public-site/components/sections/Reviews.jsx | 22 ++++++++++++++++++++- public-site/lib/schema.js | 12 +++++++++++ 16 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 public-site/lib/schema.js 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 */}