feat: страница /kontakty/, robots.txt, ai.txt, llms.txt, sitemap.txt
- /kontakty/ — email, Telegram, ВКонтакте + сетка игровых форумов - Меню обновлено: добавлен пункт «Контакты» - public/robots.txt — статика, разрешено всё; Host для Yandex; перечислены AI-краулеры (GPTBot, ClaudeBot, Google-Extended, CCBot, PerplexityBot, anthropic-ai); ссылки на оба sitemap (XML + TXT) - public/ai.txt — Train/Cite/Quote: yes, контактная почта - public/llms.txt — структура llmstxt.org с описанием проекта, ключевыми страницами, форумами, RSS-фидами, контактами - src/pages/sitemap.txt.ts — endpoint, генерит plain-text список 66 URL (главная + статика + страницы + посты + категории)
This commit is contained in:
13
public/ai.txt
Normal file
13
public/ai.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
# AI / LLM training and crawling directives for anotherreflections.ru
|
||||
# Format: see https://github.com/AnthonyJSquires/ai.txt-spec
|
||||
|
||||
User-Agent: *
|
||||
Allow: /
|
||||
|
||||
# Permission for AI use of public site content
|
||||
Train: yes
|
||||
Cite: yes
|
||||
Quote: yes
|
||||
|
||||
# Contact for questions, takedown requests, partnerships
|
||||
Contact: info@anotherreflections.ru
|
||||
41
public/llms.txt
Normal file
41
public/llms.txt
Normal file
@@ -0,0 +1,41 @@
|
||||
# Иные Отражения
|
||||
|
||||
> Ролевой проект «Иные Отражения» — независимое сообщество текстовых ролевых игр по мотивам современной фантастики. Восемь игровых вселенных, главные — Дозоры (С. Лукьяненко), Амбер (Р. Желязны), Киндрет (А. Пехов). Онлайн с 2006 года.
|
||||
|
||||
## Что это
|
||||
|
||||
Сайт-портал проекта: новости администрации (50+ публикаций с 2009 года), карточки игровых миров со ссылками на форумы, страницы «О нас» и контактов. Игра идёт на отдельных форумах, портал — точка входа.
|
||||
|
||||
## Ключевые страницы
|
||||
|
||||
- [Главная — лента новостей](https://anotherreflections.ru/)
|
||||
- [О нас](https://anotherreflections.ru/o-nas/)
|
||||
- [Миры — 8 игровых вселенных](https://anotherreflections.ru/miry/)
|
||||
- [Наши друзья](https://anotherreflections.ru/nashi-druzya/)
|
||||
- [Контакты](https://anotherreflections.ru/kontakty/)
|
||||
|
||||
## Игровые форумы
|
||||
|
||||
- [Главный форум](https://forum.anotherreflections.ru/) — общая площадка
|
||||
- [Сумерки Дозоров](https://sumerki.anotherreflections.ru/) — Дозоры (С. Лукьяненко)
|
||||
- [Амбер](https://amber.anotherreflections.ru/) — Янтарное Королевство (Р. Желязны)
|
||||
- [Киндрет](https://kindret.anotherreflections.ru/) — Кровные братья (А. Пехов)
|
||||
- [Ренессанс](https://renessans.anotherreflections.ru/) — историческая фантастика с допущениями мира Сумрака
|
||||
- [Над бездной](https://bezdna.anotherreflections.ru/) — тёмная мистика (в разработке)
|
||||
- [Глубина](https://deep.anotherreflections.ru/) — Дозоры · Глубина (в разработке)
|
||||
- [Warhammer 40k](https://warhammer40k.anotherreflections.ru/) — Сорок первое тысячелетие
|
||||
|
||||
## RSS-фиды
|
||||
|
||||
- [Общий фид](https://anotherreflections.ru/feed.xml) — все новости портала
|
||||
- Фиды по категориям: `https://anotherreflections.ru/category/<slug>/feed.xml`
|
||||
|
||||
## Контакты
|
||||
|
||||
- Электронная почта: info@anotherreflections.ru
|
||||
- Telegram: https://t.me/anotherreflections
|
||||
- ВКонтакте: https://vk.com/anotherreflections
|
||||
|
||||
## Использование
|
||||
|
||||
Контент создан администрацией и участниками проекта. Цитирование и обучение моделей разрешено (см. ai.txt). По вопросам сотрудничества — на электронную почту.
|
||||
34
public/robots.txt
Normal file
34
public/robots.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
# robots.txt for anotherreflections.ru
|
||||
# Static site (Astro), no admin area, no parametric URLs.
|
||||
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
User-agent: Yandex
|
||||
Allow: /
|
||||
Host: https://anotherreflections.ru
|
||||
|
||||
# AI/LLM crawlers — индексировать разрешено,
|
||||
# для уточнения политики обучения см. ai.txt
|
||||
User-agent: GPTBot
|
||||
Allow: /
|
||||
|
||||
User-agent: ClaudeBot
|
||||
Allow: /
|
||||
|
||||
User-agent: Google-Extended
|
||||
Allow: /
|
||||
|
||||
User-agent: CCBot
|
||||
Allow: /
|
||||
|
||||
User-agent: PerplexityBot
|
||||
Allow: /
|
||||
|
||||
User-agent: anthropic-ai
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://anotherreflections.ru/sitemap-index.xml
|
||||
Sitemap: https://anotherreflections.ru/sitemap.txt
|
||||
|
||||
Crawl-delay: 2
|
||||
@@ -3,6 +3,8 @@ export const SOCIAL = {
|
||||
vk: { url: 'https://vk.com/anotherreflections', label: 'ВКонтакте' },
|
||||
};
|
||||
|
||||
export const CONTACT_EMAIL = 'info@anotherreflections.ru';
|
||||
|
||||
/** Русская плюрализация: [1, 2-4, 5+]. Пример: plural(8, ['мир', 'мира', 'миров']) → 'миров' */
|
||||
export function plural(n: number, forms: [string, string, string]): string {
|
||||
const a = Math.abs(n) % 100;
|
||||
@@ -127,4 +129,5 @@ export const MAIN_NAV = [
|
||||
{ label: 'О нас', href: '/o-nas/' },
|
||||
{ label: 'Миры', href: '/miry/' },
|
||||
{ label: 'Друзья', href: '/nashi-druzya/' },
|
||||
{ label: 'Контакты', href: '/kontakty/' },
|
||||
];
|
||||
|
||||
50
src/pages/kontakty.astro
Normal file
50
src/pages/kontakty.astro
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
||||
import { CONTACT_EMAIL, SOCIAL, WORLDS } from '../consts';
|
||||
---
|
||||
<BaseLayout
|
||||
title="Контакты"
|
||||
description={`Связаться с проектом «Иные Отражения»: ${CONTACT_EMAIL}, Telegram, ВКонтакте.`}
|
||||
>
|
||||
<section class="hero" style="padding: 4rem 1rem 2rem;">
|
||||
<span class="hero-eyebrow">На связи</span>
|
||||
<h1>Контакты</h1>
|
||||
<p class="hero-tagline">
|
||||
Пишите нам по любым вопросам проекта: предложить идею мира, рассказать о баге форума, договориться о сотрудничестве.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="contacts">
|
||||
<a class="contact-card" href={`mailto:${CONTACT_EMAIL}`}>
|
||||
<span class="contact-label">Электронная почта</span>
|
||||
<span class="contact-value">{CONTACT_EMAIL}</span>
|
||||
<span class="contact-hint">Основной канал — отвечаем в течение нескольких дней</span>
|
||||
</a>
|
||||
<a class="contact-card" href={SOCIAL.telegram.url} target="_blank" rel="noopener">
|
||||
<span class="contact-label">Telegram-канал</span>
|
||||
<span class="contact-value">@anotherreflections</span>
|
||||
<span class="contact-hint">Анонсы, новости, объявления администрации</span>
|
||||
</a>
|
||||
<a class="contact-card" href={SOCIAL.vk.url} target="_blank" rel="noopener">
|
||||
<span class="contact-label">ВКонтакте</span>
|
||||
<span class="contact-value">vk.com/anotherreflections</span>
|
||||
<span class="contact-hint">Сообщество — здесь же открытое обсуждение</span>
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section style="margin-top: 3rem;">
|
||||
<h2 style="font-family: var(--font-serif); font-size: 1.6rem; margin-bottom: 1rem;">Игровые форумы</h2>
|
||||
<p style="color: var(--fg-muted);">Хотите включиться в игру? Заглядывайте на соответствующий форум — там модераторы каждого мира.</p>
|
||||
<ul class="worlds-grid">
|
||||
{WORLDS.map((w) => (
|
||||
<li>
|
||||
<a class="world-card" href={w.url} target="_blank" rel="noopener" style={`--cat-color: ${w.color}`}>
|
||||
<span class="world-tag">{w.tag}</span>
|
||||
<span class="world-name">{w.name}</span>
|
||||
<span class="world-desc">{w.desc}</span>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
</BaseLayout>
|
||||
29
src/pages/sitemap.txt.ts
Normal file
29
src/pages/sitemap.txt.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { APIContext } from 'astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { SITE_URL } from '../consts';
|
||||
|
||||
export async function GET(_context: APIContext) {
|
||||
const posts = await getCollection('posts');
|
||||
const pages = await getCollection('pages');
|
||||
|
||||
const staticPaths = [
|
||||
'/',
|
||||
'/miry/',
|
||||
'/kontakty/',
|
||||
];
|
||||
|
||||
// Категории — собираем из постов
|
||||
const categorySlugs = new Set<string>();
|
||||
posts.forEach((p) => p.data.categorySlugs.forEach((s) => categorySlugs.add(s)));
|
||||
|
||||
const urls = [
|
||||
...staticPaths.map((p) => new URL(p, SITE_URL).toString()),
|
||||
...pages.map((pg) => new URL(`/${pg.data.slug}/`, SITE_URL).toString()),
|
||||
...posts.map((p) => new URL(`/${p.data.slug}/`, SITE_URL).toString()),
|
||||
...Array.from(categorySlugs).map((s) => new URL(`/category/${s}/`, SITE_URL).toString()),
|
||||
];
|
||||
|
||||
return new Response(urls.join('\n') + '\n', {
|
||||
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
|
||||
});
|
||||
}
|
||||
@@ -519,6 +519,50 @@ pre {
|
||||
background: var(--bg-elev-2);
|
||||
}
|
||||
|
||||
/* ============================== CONTACTS ============================== */
|
||||
.contacts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1rem;
|
||||
margin: 1rem 0 0;
|
||||
}
|
||||
.contact-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: .4rem;
|
||||
padding: 1.5rem 1.6rem;
|
||||
background: var(--bg-elev);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
color: var(--fg);
|
||||
border-bottom: 1px solid var(--border);
|
||||
transition: border-color .25s, transform .25s, background .25s;
|
||||
}
|
||||
.contact-card:hover {
|
||||
border-color: var(--accent);
|
||||
background: var(--bg-elev-2);
|
||||
transform: translateY(-2px);
|
||||
border-bottom-color: var(--accent);
|
||||
}
|
||||
.contact-card .contact-label {
|
||||
font-size: .72rem;
|
||||
letter-spacing: 0.18em;
|
||||
text-transform: uppercase;
|
||||
color: var(--fg-dim);
|
||||
}
|
||||
.contact-card .contact-value {
|
||||
font-family: var(--font-serif);
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
color: #ebe3ff;
|
||||
}
|
||||
.contact-card:hover .contact-value { color: var(--accent); }
|
||||
.contact-card .contact-hint {
|
||||
font-size: .88rem;
|
||||
color: var(--fg-muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* ============================== SOCIAL RAIL ============================== */
|
||||
.social-rail {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user