ваше сообщение коммита
This commit is contained in:
@@ -7,13 +7,14 @@
|
||||
<title>VC HB3 Accelerator — венчурный фонд и платформа DLE</title>
|
||||
<meta name="description" content="Финтех-стартап VC HB3 Accelerator: венчурный фонд и поставщик ПО. Платформа DLE для бизнеса, акселератор, песочница. Для инвесторов, предпринимателей, регуляторов, подрядчиков." />
|
||||
<meta name="keywords" content="VC HB3 Accelerator, венчурный фонд, финтех, DLE, Digital Legal Entity, акселератор, песочница, для инвесторов, для предпринимателей, для регуляторов" />
|
||||
<link rel="canonical" href="https://hb3-accelerator.com/" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
<link rel="canonical" href="/" />
|
||||
<!-- Open Graph — информация о компании VC HB3 Accelerator -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="VC HB3 Accelerator — венчурный фонд и платформа DLE" />
|
||||
<meta property="og:description" content="Добро пожаловать в VC HB3 Accelerator. Финтех-стартап — венчурный фонд и поставщик ПО. Разрабатываем платформу DLE, помогаем бизнесу настроить и протестировать её в песочнице. Инвестируем в компании участников акселератора." />
|
||||
<meta property="og:url" content="https://hb3-accelerator.com/" />
|
||||
<meta property="og:image" content="https://hb3-accelerator.com/dle-logo.png" />
|
||||
<meta property="og:url" content="/" />
|
||||
<meta property="og:image" content="/dle-logo.png" />
|
||||
<meta property="og:locale" content="ru_RU" />
|
||||
<meta property="og:site_name" content="VC HB3 Accelerator" />
|
||||
<!-- Twitter Card -->
|
||||
|
||||
@@ -67,6 +67,20 @@ http {
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
}
|
||||
|
||||
location /blog {
|
||||
if ($arg_page != "") {
|
||||
return 301 /blog;
|
||||
}
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
location = /content/published {
|
||||
if ($arg_page != "") {
|
||||
return 301 /content/published;
|
||||
}
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Certbot webroot для автоматического получения SSL сертификатов
|
||||
location /.well-known/acme-challenge/ {
|
||||
root /var/www/certbot;
|
||||
@@ -120,6 +134,21 @@ http {
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
}
|
||||
|
||||
# Gitea служебный раздел: запрещаем индексацию
|
||||
location ^~ /gitea/ {
|
||||
proxy_pass http://dapp-gitea:3000/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
add_header X-Robots-Tag "noindex, nofollow, noarchive, nosnippet, noimageindex" always;
|
||||
proxy_redirect off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_connect_timeout 120s;
|
||||
proxy_send_timeout 1800s;
|
||||
proxy_read_timeout 1800s;
|
||||
}
|
||||
|
||||
# Скрытие информации о сервере
|
||||
server_tokens off;
|
||||
}
|
||||
|
||||
@@ -221,6 +221,7 @@ http {
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
add_header X-Robots-Tag "noindex, nofollow, noarchive, nosnippet, noimageindex" always;
|
||||
proxy_redirect off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_connect_timeout 120s;
|
||||
@@ -253,6 +254,9 @@ http {
|
||||
|
||||
# Pre-rendered blog pages (SEO optimization)
|
||||
location /blog {
|
||||
if ($arg_page != "") {
|
||||
return 301 /blog;
|
||||
}
|
||||
root /usr/share/nginx/html;
|
||||
try_files $uri $uri.html /blog/index.html /index.html;
|
||||
|
||||
@@ -262,6 +266,13 @@ http {
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
}
|
||||
|
||||
location = /content/published {
|
||||
if ($arg_page != "") {
|
||||
return 301 /content/published;
|
||||
}
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Статические файлы
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 1y;
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted, watch, nextTick } from 'vue';
|
||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { marked } from 'marked';
|
||||
import DOMPurify from 'dompurify';
|
||||
@@ -220,6 +220,23 @@ const relatedArticles = ref([]);
|
||||
|
||||
// Определяем, это страница блога
|
||||
const isBlogPage = computed(() => route.path.startsWith('/blog'));
|
||||
const isPublishedPage = computed(() => route.path.startsWith('/content/published'));
|
||||
const shouldManageNoindex = computed(() => isBlogPage.value || isPublishedPage.value);
|
||||
|
||||
function setRobotsMeta(content = 'index, follow') {
|
||||
let robotsMeta = document.querySelector('meta[name="robots"]');
|
||||
if (!robotsMeta) {
|
||||
robotsMeta = document.createElement('meta');
|
||||
robotsMeta.setAttribute('name', 'robots');
|
||||
document.head.appendChild(robotsMeta);
|
||||
}
|
||||
// Не выставляем noindex вне документных маршрутов, чтобы не блокировать индексацию главной.
|
||||
if (content.startsWith('noindex') && !shouldManageNoindex.value) {
|
||||
robotsMeta.setAttribute('content', 'index, follow');
|
||||
return;
|
||||
}
|
||||
robotsMeta.setAttribute('content', content);
|
||||
}
|
||||
|
||||
// Установка мета-тегов для SEO
|
||||
function updateMetaTags(pageData) {
|
||||
@@ -240,22 +257,21 @@ function updateMetaTags(pageData) {
|
||||
const description = seoData?.description || pageData.summary || '';
|
||||
const keywords = seoData?.keywords || '';
|
||||
|
||||
// Определяем canonical URL в зависимости от текущего маршрута и наличия slug
|
||||
// Определяем canonical URL только по slug (без fallback на ?page=, чтобы исключить дубли)
|
||||
const currentPath = window.location.pathname;
|
||||
let canonicalUrl;
|
||||
if (currentPath.startsWith('/blog')) {
|
||||
// Используем slug если есть, иначе fallback на query параметр
|
||||
if (pageData.slug && typeof pageData.slug === 'string' && pageData.slug.trim() !== '') {
|
||||
canonicalUrl = `${window.location.origin}/blog/${encodeURIComponent(pageData.slug)}`;
|
||||
} else if (pageData.id) {
|
||||
canonicalUrl = `${window.location.origin}/blog?page=${pageData.id}`;
|
||||
} else {
|
||||
canonicalUrl = `${window.location.origin}/blog`;
|
||||
if (!pageData.slug || typeof pageData.slug !== 'string' || pageData.slug.trim() === '') {
|
||||
setRobotsMeta('noindex, follow');
|
||||
return;
|
||||
}
|
||||
canonicalUrl = `${window.location.origin}/blog/${encodeURIComponent(pageData.slug.trim())}`;
|
||||
} else {
|
||||
canonicalUrl = pageData.id
|
||||
? `${window.location.origin}/content/published?page=${pageData.id}`
|
||||
: `${window.location.origin}/content/published`;
|
||||
if (!pageData.slug || typeof pageData.slug !== 'string' || pageData.slug.trim() === '') {
|
||||
setRobotsMeta('noindex, follow');
|
||||
return;
|
||||
}
|
||||
canonicalUrl = `${window.location.origin}/content/published/${encodeURIComponent(pageData.slug.trim())}`;
|
||||
}
|
||||
|
||||
// Обновляем title
|
||||
@@ -297,7 +313,7 @@ function updateMetaTags(pageData) {
|
||||
updateOrCreateMeta('og:url', canonicalUrl, 'property');
|
||||
|
||||
// Robots meta
|
||||
updateOrCreateMeta('robots', 'index, follow');
|
||||
setRobotsMeta('index, follow');
|
||||
|
||||
// Добавляем JSON-LD разметку для статьи
|
||||
addArticleJsonLd(pageData, canonicalUrl);
|
||||
@@ -487,11 +503,19 @@ async function loadPage() {
|
||||
if (error.response?.data && error.response.status !== 404) {
|
||||
console.warn('[DocsContent] Пытаемся использовать данные из error.response.data');
|
||||
page.value = error.response.data;
|
||||
if (!page.value || !page.value.id) {
|
||||
setRobotsMeta('noindex, follow');
|
||||
}
|
||||
} else {
|
||||
page.value = null;
|
||||
page.value = null;
|
||||
// Для любого error-state показываем noindex, иначе Google получает soft-404.
|
||||
setRobotsMeta('noindex, follow');
|
||||
}
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
if (!page.value) {
|
||||
setRobotsMeta('noindex, follow');
|
||||
}
|
||||
console.log('[DocsContent] loadPage завершен:', {
|
||||
hasPage: !!page.value,
|
||||
isLoading: isLoading.value,
|
||||
@@ -831,6 +855,11 @@ onMounted(() => {
|
||||
}
|
||||
setupVideoErrorHandlers();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
// В SPA noindex может "залипать" между маршрутами, поэтому сбрасываем его при уходе со страницы документа.
|
||||
setRobotsMeta('index, follow');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -243,11 +243,12 @@ function addBlogJsonLd() {
|
||||
'name': 'Блог',
|
||||
'description': 'Публикации и статьи',
|
||||
'url': `${window.location.origin}/blog`,
|
||||
'blogPost': pages.value.slice(0, 10).map(page => {
|
||||
const url = (page.slug && typeof page.slug === 'string' && page.slug.trim() !== '')
|
||||
? `${window.location.origin}/blog/${encodeURIComponent(page.slug)}`
|
||||
: (page.id ? `${window.location.origin}/blog?page=${page.id}` : `${window.location.origin}/blog`);
|
||||
|
||||
'blogPost': pages.value
|
||||
.filter(page => page.slug && typeof page.slug === 'string' && page.slug.trim() !== '')
|
||||
.slice(0, 10)
|
||||
.map(page => {
|
||||
const url = `${window.location.origin}/blog/${encodeURIComponent(page.slug.trim())}`;
|
||||
|
||||
return {
|
||||
'@type': 'BlogPosting',
|
||||
'headline': page.title || '',
|
||||
|
||||
@@ -266,9 +266,21 @@ function updatePageMetaTags() {
|
||||
const keywords = seoData?.keywords || '';
|
||||
|
||||
// Определяем canonical URL
|
||||
const pageUrl = page.value.slug
|
||||
? `${window.location.origin}/content/published/${encodeURIComponent(page.value.slug)}`
|
||||
: `${window.location.origin}/content/published?page=${page.value.id}`;
|
||||
if (!page.value.slug || typeof page.value.slug !== 'string' || page.value.slug.trim() === '') {
|
||||
// Без slug страницу не индексируем, чтобы не плодить дубли по ?page=
|
||||
const robotsMeta = document.querySelector('meta[name="robots"]');
|
||||
if (robotsMeta) {
|
||||
robotsMeta.setAttribute('content', 'noindex, follow');
|
||||
} else {
|
||||
const meta = document.createElement('meta');
|
||||
meta.setAttribute('name', 'robots');
|
||||
meta.setAttribute('content', 'noindex, follow');
|
||||
document.head.appendChild(meta);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const pageUrl = `${window.location.origin}/content/published/${encodeURIComponent(page.value.slug.trim())}`;
|
||||
|
||||
// Обновляем title
|
||||
document.title = title;
|
||||
|
||||
Reference in New Issue
Block a user