diff --git a/public/ai.txt b/public/ai.txt new file mode 100644 index 0000000..f120039 --- /dev/null +++ b/public/ai.txt @@ -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 diff --git a/public/llms.txt b/public/llms.txt new file mode 100644 index 0000000..9cca2ee --- /dev/null +++ b/public/llms.txt @@ -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//feed.xml` + +## Контакты + +- Электронная почта: info@anotherreflections.ru +- Telegram: https://t.me/anotherreflections +- ВКонтакте: https://vk.com/anotherreflections + +## Использование + +Контент создан администрацией и участниками проекта. Цитирование и обучение моделей разрешено (см. ai.txt). По вопросам сотрудничества — на электронную почту. diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..a7ad6a1 --- /dev/null +++ b/public/robots.txt @@ -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 diff --git a/src/consts.ts b/src/consts.ts index 05954f7..a51a7c5 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -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/' }, ]; diff --git a/src/pages/kontakty.astro b/src/pages/kontakty.astro new file mode 100644 index 0000000..e56246a --- /dev/null +++ b/src/pages/kontakty.astro @@ -0,0 +1,50 @@ +--- +import BaseLayout from '../layouts/BaseLayout.astro'; +import { CONTACT_EMAIL, SOCIAL, WORLDS } from '../consts'; +--- + +
+ На связи +

Контакты

+

+ Пишите нам по любым вопросам проекта: предложить идею мира, рассказать о баге форума, договориться о сотрудничестве. +

+
+ +
+ + Электронная почта + {CONTACT_EMAIL} + Основной канал — отвечаем в течение нескольких дней + + + Telegram-канал + @anotherreflections + Анонсы, новости, объявления администрации + + + ВКонтакте + vk.com/anotherreflections + Сообщество — здесь же открытое обсуждение + +
+ +
+

Игровые форумы

+

Хотите включиться в игру? Заглядывайте на соответствующий форум — там модераторы каждого мира.

+ +
+
diff --git a/src/pages/sitemap.txt.ts b/src/pages/sitemap.txt.ts new file mode 100644 index 0000000..11a3103 --- /dev/null +++ b/src/pages/sitemap.txt.ts @@ -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(); + 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' }, + }); +} diff --git a/src/styles/global.css b/src/styles/global.css index 1f066ed..f086fd0 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -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;