diff --git a/public/ai-dev/index.html b/public/ai-dev/index.html index 66e9ae7..d59ec6c 100644 --- a/public/ai-dev/index.html +++ b/public/ai-dev/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/ai-assistant-figma/index.html b/public/cases/ai-assistant-figma/index.html index 097d501..794d3d4 100644 --- a/public/cases/ai-assistant-figma/index.html +++ b/public/cases/ai-assistant-figma/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/ai-platform-primo-rpa-2/index.html b/public/cases/ai-platform-primo-rpa-2/index.html index 300b7e8..273c285 100644 --- a/public/cases/ai-platform-primo-rpa-2/index.html +++ b/public/cases/ai-platform-primo-rpa-2/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/ai-platform-primo-rpa-v2/index.html b/public/cases/ai-platform-primo-rpa-v2/index.html index fc3e1a3..93d3735 100644 --- a/public/cases/ai-platform-primo-rpa-v2/index.html +++ b/public/cases/ai-platform-primo-rpa-v2/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/ai-platform-primo-rpa/index.html b/public/cases/ai-platform-primo-rpa/index.html index 9076d1e..4c58014 100644 --- a/public/cases/ai-platform-primo-rpa/index.html +++ b/public/cases/ai-platform-primo-rpa/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/card-columns-obsidian/index.html b/public/cases/card-columns-obsidian/index.html index 6ea3afc..bb78773 100644 --- a/public/cases/card-columns-obsidian/index.html +++ b/public/cases/card-columns-obsidian/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/design-system/index.html b/public/cases/design-system/index.html index cf6f604..5480667 100644 --- a/public/cases/design-system/index.html +++ b/public/cases/design-system/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/lunacy/index.html b/public/cases/lunacy/index.html index 1bd7cc8..83621e2 100644 --- a/public/cases/lunacy/index.html +++ b/public/cases/lunacy/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/manu-game-maker/index.html b/public/cases/manu-game-maker/index.html index 2cc7ccf..f17ce3d 100644 --- a/public/cases/manu-game-maker/index.html +++ b/public/cases/manu-game-maker/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/mini-projects-showcase/index.html b/public/cases/mini-projects-showcase/index.html index cd677c3..9eda2d5 100644 --- a/public/cases/mini-projects-showcase/index.html +++ b/public/cases/mini-projects-showcase/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/mobile-clinic-app/index.html b/public/cases/mobile-clinic-app/index.html index 8dbae8c..3877358 100644 --- a/public/cases/mobile-clinic-app/index.html +++ b/public/cases/mobile-clinic-app/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/obsidian-plugin-columns-view/index.html b/public/cases/obsidian-plugin-columns-view/index.html index c577bbb..ca6eb6a 100644 --- a/public/cases/obsidian-plugin-columns-view/index.html +++ b/public/cases/obsidian-plugin-columns-view/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/orc-automation-panel/index.html b/public/cases/orc-automation-panel/index.html index f007298..72271bf 100644 --- a/public/cases/orc-automation-panel/index.html +++ b/public/cases/orc-automation-panel/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/site-portfolio/index.html b/public/cases/site-portfolio/index.html index d9389c6..3dcfa27 100644 --- a/public/cases/site-portfolio/index.html +++ b/public/cases/site-portfolio/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/task-distribution-concept/index.html b/public/cases/task-distribution-concept/index.html index 2dae746..3ee9a38 100644 --- a/public/cases/task-distribution-concept/index.html +++ b/public/cases/task-distribution-concept/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/task-tracker/index.html b/public/cases/task-tracker/index.html index 8dadcdb..3209015 100644 --- a/public/cases/task-tracker/index.html +++ b/public/cases/task-tracker/index.html @@ -114,6 +114,7 @@ + diff --git a/public/cases/template-elements-demo/index.html b/public/cases/template-elements-demo/index.html index 8b63354..6ff74a6 100644 --- a/public/cases/template-elements-demo/index.html +++ b/public/cases/template-elements-demo/index.html @@ -111,6 +111,7 @@ + diff --git a/public/cookie-policy/index.html b/public/cookie-policy/index.html index b2be932..65690b1 100644 --- a/public/cookie-policy/index.html +++ b/public/cookie-policy/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/ai-assistant-figma/index.html b/public/en/cases/ai-assistant-figma/index.html index c68ebd9..573be29 100644 --- a/public/en/cases/ai-assistant-figma/index.html +++ b/public/en/cases/ai-assistant-figma/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/ai-platform-primo-rpa-2/index.html b/public/en/cases/ai-platform-primo-rpa-2/index.html index 30c86ad..a70cd5d 100644 --- a/public/en/cases/ai-platform-primo-rpa-2/index.html +++ b/public/en/cases/ai-platform-primo-rpa-2/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/ai-platform-primo-rpa-v2/index.html b/public/en/cases/ai-platform-primo-rpa-v2/index.html index b4851a7..e35d3d2 100644 --- a/public/en/cases/ai-platform-primo-rpa-v2/index.html +++ b/public/en/cases/ai-platform-primo-rpa-v2/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/ai-platform-primo-rpa/index.html b/public/en/cases/ai-platform-primo-rpa/index.html index 24ede7d..4e1c85f 100644 --- a/public/en/cases/ai-platform-primo-rpa/index.html +++ b/public/en/cases/ai-platform-primo-rpa/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/card-columns-obsidian/index.html b/public/en/cases/card-columns-obsidian/index.html index 7328974..ddd8648 100644 --- a/public/en/cases/card-columns-obsidian/index.html +++ b/public/en/cases/card-columns-obsidian/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/design-system/index.html b/public/en/cases/design-system/index.html index 769d174..31ba2cb 100644 --- a/public/en/cases/design-system/index.html +++ b/public/en/cases/design-system/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/lunacy/index.html b/public/en/cases/lunacy/index.html index d32fdd1..d9f0498 100644 --- a/public/en/cases/lunacy/index.html +++ b/public/en/cases/lunacy/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/manu-game-maker/index.html b/public/en/cases/manu-game-maker/index.html index c3da12e..976c70a 100644 --- a/public/en/cases/manu-game-maker/index.html +++ b/public/en/cases/manu-game-maker/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/mini-projects-showcase/index.html b/public/en/cases/mini-projects-showcase/index.html index 4dca4e3..0ed6aa3 100644 --- a/public/en/cases/mini-projects-showcase/index.html +++ b/public/en/cases/mini-projects-showcase/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/mobile-clinic-app/index.html b/public/en/cases/mobile-clinic-app/index.html index f2ff754..a89dee1 100644 --- a/public/en/cases/mobile-clinic-app/index.html +++ b/public/en/cases/mobile-clinic-app/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/obsidian-plugin-columns-view/index.html b/public/en/cases/obsidian-plugin-columns-view/index.html index 1178657..9d2c305 100644 --- a/public/en/cases/obsidian-plugin-columns-view/index.html +++ b/public/en/cases/obsidian-plugin-columns-view/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/orc-automation-panel/index.html b/public/en/cases/orc-automation-panel/index.html index 0c92b25..8bedb16 100644 --- a/public/en/cases/orc-automation-panel/index.html +++ b/public/en/cases/orc-automation-panel/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/site-portfolio/index.html b/public/en/cases/site-portfolio/index.html index 051aec6..c847950 100644 --- a/public/en/cases/site-portfolio/index.html +++ b/public/en/cases/site-portfolio/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/task-distribution-concept/index.html b/public/en/cases/task-distribution-concept/index.html index b3c1a62..60ec1ff 100644 --- a/public/en/cases/task-distribution-concept/index.html +++ b/public/en/cases/task-distribution-concept/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/task-tracker/index.html b/public/en/cases/task-tracker/index.html index 3a88b1f..cdc257f 100644 --- a/public/en/cases/task-tracker/index.html +++ b/public/en/cases/task-tracker/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/cases/template-elements-demo/index.html b/public/en/cases/template-elements-demo/index.html index eee879b..96288ee 100644 --- a/public/en/cases/template-elements-demo/index.html +++ b/public/en/cases/template-elements-demo/index.html @@ -111,6 +111,7 @@ + diff --git a/public/en/cookie-policy/index.html b/public/en/cookie-policy/index.html index 45ccb39..457dfb8 100644 --- a/public/en/cookie-policy/index.html +++ b/public/en/cookie-policy/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/index.html b/public/en/index.html index 369ed38..6f96a20 100644 --- a/public/en/index.html +++ b/public/en/index.html @@ -114,6 +114,7 @@ + diff --git a/public/en/resume/index.html b/public/en/resume/index.html index 9369ecc..a12d61c 100644 --- a/public/en/resume/index.html +++ b/public/en/resume/index.html @@ -114,6 +114,7 @@ + diff --git a/public/index.html b/public/index.html index 60847ba..8890b9e 100644 --- a/public/index.html +++ b/public/index.html @@ -114,6 +114,7 @@ + diff --git a/public/llms.txt b/public/llms.txt new file mode 100644 index 0000000..901a3ac --- /dev/null +++ b/public/llms.txt @@ -0,0 +1,39 @@ +# Николай Мамадаев — продуктовый дизайнер + +> Сайт-портфолио продуктового дизайнера Николая Мамадаева: кейсы UX/UI-проектов, резюме, описание AI-разработки и контакты. Русский и английский, английские страницы лежат в /en/. + +Формат: [llms.txt](https://llmstxt.org/). Карта для поисковиков: https://mamadaevv.site/sitemap.xml, правила для краулеров: https://mamadaevv.site/robots.txt. + +Ссылки ведут на HTML-страницы, отдельной markdown-версии у сайта нет. Страницы-каталоги дизайн-системы (/cases/design-system/, /cases/template-elements-demo/, /cases/mini-projects-showcase/) закрыты от индексации и сюда не попали. + +## Основные страницы + +- [AI-разработка](https://mamadaevv.site/ai-dev/): Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты. +- [Политика cookie](https://mamadaevv.site/cookie-policy/): Какие cookie и localStorage использует сайт. +- [Главная](https://mamadaevv.site/): Короткое описание, портфолио из кейсов и лента активности. +- [Резюме](https://mamadaevv.site/resume/): Опыт работы, стек, проекты, навыки и контакты. + +## Кейсы + +- [AI assistant: плагин-мост между Cursor и Figma](https://mamadaevv.site/cases/ai-assistant-figma/): Получает скрипты из Cursor и выполняет их в открытом файле. +- [AI Server в Primo RPA: черновик 2](https://mamadaevv.site/cases/ai-platform-primo-rpa-2/): Черновик 2: OCR на документах, дообучение моделей, skills. +- [AI Server в Primo RPA: редизайн](https://mamadaevv.site/cases/ai-platform-primo-rpa-v2/): Редизайн интерфейса AI Server. +- [Настройка AI Server без помощи внедрения](https://mamadaevv.site/cases/ai-platform-primo-rpa/): Фреймворк STAR для настройки проектов в AI Server. +- [Card Columns для Obsidian Bases](https://mamadaevv.site/cases/card-columns-obsidian/): Канбан-доски по свойствам заметок, фильтры AND/OR, перенос карточек. +- [Lunacy](https://mamadaevv.site/cases/lunacy/): Icons8: пользовательские сценарии, итерации интерфейса и скриншоты процесса. +- [Игровой движок MANU](https://mamadaevv.site/cases/manu-game-maker/): Визуальная система и сложные пользовательские сценарии. +- [Мобильное приложение для сети клиник](https://mamadaevv.site/cases/mobile-clinic-app/): Запись к врачу, услуги, навигация, быстрые действия. +- [Колоночный вид для Obsidian](https://mamadaevv.site/cases/obsidian-plugin-columns-view/): Дизайн и UX плагина для заметок. +- [Веб-панель для оркестрации автоматизаций](https://mamadaevv.site/cases/orc-automation-panel/): Primo RPA: кураторство дизайна, переход на Ant Design и Storybook, токены в Figma. +- [Как я создаю сайт-портфолио с LLM-агентами](https://mamadaevv.site/cases/site-portfolio/): От no-code конструкторов до разработки в Cursor и Hermes Agent. +- [Концепт сервиса распределения задач](https://mamadaevv.site/cases/task-distribution-concept/): Прозрачность процессов между командами. +- [Таск-трекер для бек-офис системы](https://mamadaevv.site/cases/task-tracker/): Вкладки, фильтры, виды отображения, прототипы и пользовательские исследования. + +## Контакты + +- [Telegram](https://t.me/mamadaevv): @mamadaevv +- [Почта](mailto:nik@mamadaevv.site): nik@mamadaevv.site + +## Использование + +Цитировать кейсы и текст можно со ссылкой на страницу. Ссылка на сайт обязательна. diff --git a/public/resume/index.html b/public/resume/index.html index 0e28566..45754a0 100644 --- a/public/resume/index.html +++ b/public/resume/index.html @@ -114,6 +114,7 @@ + diff --git a/scripts/build-pages.mjs b/scripts/build-pages.mjs index 58c08e3..e4f5d97 100644 --- a/scripts/build-pages.mjs +++ b/scripts/build-pages.mjs @@ -35,6 +35,39 @@ const PER_PAGE_OG_IMAGE = { "cases/ai-platform-primo-rpa": `${SITE_ORIGIN}/assets/og/og-primo-star.png`, }; +// По одной строке на страницу — попадает в llms.txt. +// Пишется от руки: description из у кейсов начинается со слов «Кейс:» +// и сам по себе ни о чём не говорит агенту. Правило: не повторять имя ссылки +// (оно уже стоит слева от двоеточия) и не писать «Кейс: …». +const LLMS_PAGE_NOTES = { + "": "Короткое описание, портфолио из кейсов и лента активности.", + resume: "Опыт работы, стек, проекты, навыки и контакты.", + "ai-dev": "Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты.", + "cookie-policy": "Какие cookie и localStorage использует сайт.", + "cases/ai-assistant-figma": "Получает скрипты из Cursor и выполняет их в открытом файле.", + "cases/ai-platform-primo-rpa": "Фреймворк STAR для настройки проектов в AI Server.", + "cases/ai-platform-primo-rpa-v2": "Редизайн интерфейса AI Server.", + "cases/ai-platform-primo-rpa-2": "Черновик 2: OCR на документах, дообучение моделей, skills.", + "cases/card-columns-obsidian": "Канбан-доски по свойствам заметок, фильтры AND/OR, перенос карточек.", + "cases/lunacy": "Icons8: пользовательские сценарии, итерации интерфейса и скриншоты процесса.", + "cases/manu-game-maker": "Визуальная система и сложные пользовательские сценарии.", + "cases/mobile-clinic-app": "Запись к врачу, услуги, навигация, быстрые действия.", + "cases/obsidian-plugin-columns-view": "Дизайн и UX плагина для заметок.", + "cases/orc-automation-panel": + "Primo RPA: кураторство дизайна, переход на Ant Design и Storybook, токены в Figma.", + "cases/site-portfolio": "От no-code конструкторов до разработки в Cursor и Hermes Agent.", + "cases/task-distribution-concept": "Прозрачность процессов между командами.", + "cases/task-tracker": "Вкладки, фильтры, виды отображения, прототипы и пользовательские исследования.", +}; + +// Имя ссылки, когда заголовок страницы не отвечает на вопрос «что это». +// Заодно снимаем хвост «— кейс» / «— Case Study»: в секции «Кейсы» он лишний. +const LLMS_PAGE_NAMES = { + "cases/ai-platform-primo-rpa-v2": "AI Server в Primo RPA: редизайн", + "cases/ai-platform-primo-rpa-2": "AI Server в Primo RPA: черновик 2", + "cases/card-columns-obsidian": "Card Columns для Obsidian Bases", +}; + const titleRe = /([\s\S]*?)<\/title>/i; const descRe = /<meta\s+name="description"\s+content="([\s\S]*?)"\s*\/?>/i; @@ -205,6 +238,65 @@ function buildSitemap(pageFiles) { ); } +/** Генерация llms.txt: короткая карта сайта для LLM-агентов (спецификация llmstxt.org). */ +function buildLlmsTxt(pageFiles) { + const entries = []; + for (const pagePath of pageFiles) { + const relNorm = path.relative(srcPagesDir, pagePath).split(path.sep).join("/"); + // Тот же slug, что и в sitePath(): index.html → "" (главная). + const slug = relNorm + .replace(/\.html$/, "") + .replace(/(^|\/)index$/, "") + .replace(/\/$/, ""); + if (NOINDEX_PAGES.has(slug)) continue; + const { title } = extractMeta(readUtf8(pagePath)); + // Имя ссылки: из <title> без хвоста с фамилией автора и без «— кейс», + // но с явным переопределением там, где заголовок говорит только «AI Server». + const strippedTitle = title + ? title + .replace(/\s*[·|—-]\s*Никол(ая|ай) Мамадаев\s*$/i, "") + .replace(/\s*[—–-]\s*(кейс|case study)\s*$/i, "") + .trim() + : ""; + const name = + LLMS_PAGE_NAMES[slug] || (slug === "" ? "Главная" : strippedTitle || slug); + entries.push({ slug, name, url: canonicalFor(relNorm, DEFAULT_LOCALE) }); + } + const cases = entries.filter((e) => e.slug.startsWith("cases/")); + const rest = entries.filter((e) => !e.slug.startsWith("cases/")); + + /** Строка списка: описание дописывается, только если не повторяет имя ссылки. */ + const line = (e) => { + const note = LLMS_PAGE_NOTES[e.slug] || ""; + if (!note) return `- [${e.name}](${e.url})`; + // Описание, начинающееся именем ссылки, обрезаем: «Имя: Имя: …» агентам не помогает. + const prefix = `${e.name}: `; + const trimmed = note.startsWith(prefix) ? note.slice(prefix.length) : note; + return `- [${e.name}](${e.url}): ${trimmed}`; + }; + const section = (heading, list) => `## ${heading}\n\n${list.map(line).join("\n")}\n`; + + return ( + `# ${SITE_NAME_RU}\n\n` + + `> Сайт-портфолио продуктового дизайнера Николая Мамадаева: кейсы UX/UI-проектов, резюме, ` + + `описание AI-разработки и контакты. Русский и английский, английские страницы лежат в /en/.\n\n` + + `Формат: [llms.txt](https://llmstxt.org/). Карта для поисковиков: ` + + `https://mamadaevv.site/sitemap.xml, правила для краулеров: https://mamadaevv.site/robots.txt.\n\n` + + `Ссылки ведут на HTML-страницы, отдельной markdown-версии у сайта нет. ` + + `Страницы-каталоги дизайн-системы (/cases/design-system/, /cases/template-elements-demo/, ` + + `/cases/mini-projects-showcase/) закрыты от индексации и сюда не попали.\n\n` + + section("Основные страницы", rest) + + "\n" + + section("Кейсы", cases) + + "\n" + + `## Контакты\n\n` + + `- [Telegram](https://t.me/mamadaevv): @mamadaevv\n` + + `- [Почта](mailto:nik@mamadaevv.site): nik@mamadaevv.site\n\n` + + `## Использование\n\n` + + `Цитировать кейсы и текст можно со ссылкой на страницу. Ссылка на сайт обязательна.\n` + ); +} + const includeRe = /\{\{\>\s*([a-z0-9-]+)\s*\}\}/gi; const varRe = /\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g; const i18nRe = /\{\{\s*i18n:([\w.-]+)\s*\}\}/g; @@ -391,6 +483,8 @@ function build() { vars.ogDescription = pageDesc; vars.ogImage = PER_PAGE_OG_IMAGE[noSlug] || OG_IMAGE_DEFAULT; vars.ogImageAlt = pageTitle; + // Link-relation v2 спецификации llms.txt: файл, покрывающий страницу. + vars.llmsUrl = `${SITE_ORIGIN}/llms.txt`; vars.jsonLd = JSON.stringify(buildJsonLd(relNorm, loc, { title: pageTitle, description: pageDesc }, canonicalUrl), null, 2); // Префикс до КОРНЯ ЛОКАЛИ (без en-сдвига) — для навигационных ссылок, @@ -432,8 +526,12 @@ function build() { const sitemapXml = buildSitemap(pageFiles); fs.writeFileSync(path.join(outDir, "sitemap.xml"), sitemapXml, "utf8"); + const llmsTxt = buildLlmsTxt(pageFiles); + fs.writeFileSync(path.join(outDir, "llms.txt"), llmsTxt, "utf8"); + console.log(`Built ${pageFiles.length} pages × ${LOCALES.length} locales into public/`); console.log(`Generated sitemap.xml (${sitemapXml.split("<url>").length - 1} urls)`); + console.log(`Generated llms.txt (${llmsTxt.split("\n").filter((l) => l.startsWith("- [")).length} links)`); } build(); diff --git a/src/partials/head-seo.html b/src/partials/head-seo.html index 7ae5777..7ae31db 100644 --- a/src/partials/head-seo.html +++ b/src/partials/head-seo.html @@ -2,6 +2,7 @@ <link rel="alternate" hreflang="ru" href="{{canonicalRu}}" /> <link rel="alternate" hreflang="en" href="{{canonicalEn}}" /> <link rel="alternate" hreflang="x-default" href="{{canonicalRu}}" /> + <link rel="describedby" href="{{llmsUrl}}" title="llms.txt" /> <meta name="author" content="{{authorName}}" /> <meta name="robots" content="{{metaRobots}}" /> <meta name="theme-color" content="{{themeColor}}" />