All checks were successful
deploy / deploy (push) Successful in 1m0s
Entity-сигнал для AI Overviews / Я.Нейро о тех-партнёрстве. Связывает сайт с разработчиком через @id графа. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
138 lines
4.1 KiB
Plaintext
138 lines
4.1 KiB
Plaintext
---
|
||
import '../styles/global.css';
|
||
import Header from '../components/Header.astro';
|
||
import Sidebar from '../components/Sidebar.astro';
|
||
import Footer from '../components/Footer.astro';
|
||
import CookieConsent from '../components/CookieConsent.astro';
|
||
import Analytics from '../components/Analytics.astro';
|
||
import { SITE_TITLE, SITE_DESCRIPTION, SITE_URL, SITE_LANG } from '../consts';
|
||
|
||
interface Props {
|
||
title?: string;
|
||
description?: string;
|
||
ogImage?: string;
|
||
noSidebar?: boolean;
|
||
canonical?: string;
|
||
}
|
||
|
||
const {
|
||
title,
|
||
description = SITE_DESCRIPTION,
|
||
ogImage = '/og-image.png',
|
||
noSidebar = false,
|
||
canonical,
|
||
} = Astro.props;
|
||
|
||
const fullTitle = title ? `${title} — ${SITE_TITLE}` : SITE_TITLE;
|
||
const url = canonical ?? new URL(Astro.url.pathname, SITE_URL).toString();
|
||
const ogImageUrl = new URL(ogImage, SITE_URL).toString();
|
||
|
||
const jsonLd = {
|
||
'@context': 'https://schema.org',
|
||
'@graph': [
|
||
{
|
||
'@type': 'WebSite',
|
||
'@id': `${SITE_URL}/#website`,
|
||
url: `${SITE_URL}/`,
|
||
name: SITE_TITLE,
|
||
description: SITE_DESCRIPTION,
|
||
inLanguage: 'ru-RU',
|
||
publisher: { '@id': `${SITE_URL}/#publisher` },
|
||
// creator — тех-партнёр (hhivp.com). Entity-сигнал для AI Overviews.
|
||
creator: {
|
||
'@type': 'Organization',
|
||
'@id': 'https://hhivp.com/#organization',
|
||
name: 'ООО «АйТи Решения»',
|
||
url: 'https://hhivp.com/',
|
||
sameAs: ['https://hhivp.com'],
|
||
},
|
||
},
|
||
{
|
||
'@type': 'NewsMediaOrganization',
|
||
'@id': `${SITE_URL}/#publisher`,
|
||
name: SITE_TITLE,
|
||
url: `${SITE_URL}/`,
|
||
logo: {
|
||
'@type': 'ImageObject',
|
||
url: `${SITE_URL}/favicon.svg`,
|
||
},
|
||
description:
|
||
'Краеведческое медиа: история, новости и фотолетопись подмосковного города Пушкино — от давних времён до наших дней.',
|
||
},
|
||
],
|
||
};
|
||
---
|
||
|
||
<!doctype html>
|
||
<html lang={SITE_LANG}>
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>{fullTitle}</title>
|
||
<meta name="description" content={description} />
|
||
<link rel="canonical" href={url} />
|
||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||
<link rel="alternate" type="application/rss+xml" title="История города Пушкино — RSS" href="/feed.xml" />
|
||
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:title" content={fullTitle} />
|
||
<meta property="og:description" content={description} />
|
||
<meta property="og:url" content={url} />
|
||
<meta property="og:image" content={ogImageUrl} />
|
||
<meta property="og:locale" content="ru_RU" />
|
||
<meta property="og:site_name" content={SITE_TITLE} />
|
||
<meta name="twitter:card" content="summary_large_image" />
|
||
|
||
<script type="application/ld+json" is:inline set:html={JSON.stringify(jsonLd)} />
|
||
|
||
<!--
|
||
Speculation Rules API (Chromium 122+) — prerender same-origin pages on
|
||
hover/pointerdown for near-instant navigation.
|
||
-->
|
||
<script type="speculationrules" is:inline set:html={JSON.stringify({
|
||
prerender: [
|
||
{
|
||
where: {
|
||
and: [
|
||
{ href_matches: '/*' },
|
||
{ not: { href_matches: '/assets/*' } },
|
||
{ not: { href_matches: '/uploads/*' } },
|
||
{ not: { href_matches: '/api/*' } },
|
||
{ not: { href_matches: '/sitemap*' } },
|
||
{ not: { href_matches: '/feed*' } },
|
||
{ not: { href_matches: '/llms*' } }
|
||
]
|
||
},
|
||
eagerness: 'moderate'
|
||
}
|
||
]
|
||
})} />
|
||
|
||
<Analytics />
|
||
</head>
|
||
<body>
|
||
<Header />
|
||
<div class="container">
|
||
{noSidebar ? (
|
||
<main class="layout-single">
|
||
<slot />
|
||
</main>
|
||
) : (
|
||
<div class="layout-grid">
|
||
<main><slot /></main>
|
||
<Sidebar />
|
||
</div>
|
||
)}
|
||
</div>
|
||
<Footer />
|
||
<CookieConsent />
|
||
</body>
|
||
</html>
|
||
|
||
<style>
|
||
.layout-single {
|
||
max-width: var(--reading-max);
|
||
margin: 2rem auto;
|
||
}
|
||
</style>
|