design: redesign ai-dev with expressive type and project grid
This commit is contained in:
1 parent
be7da3d0ec
commit
f4404edaca
6 files changed
+267
-318
No files matched your search
@@ -186,6 +186,13 @@
|
||||
| `.skill-task-card` | Карточка навыка (задача + решения) |
|
||||
| `.contact-card` | Контактная карточка (ссылка или действие) |
|
||||
|
||||
### Сетка проектов
|
||||
|
||||
| Класс | Назначение |
|
||||
|---|---|
|
||||
| `.project-grid` | Сетка карточек проекта: 1 колонка на мобильном, 2 от `680px`, 3 от `1120px`; адаптивные интервалы между карточками |
|
||||
| `.project-grid > li` | Элемент списка без собственного оформления; внутри используется компонент карточки, например `.mp-card` |
|
||||
|
||||
### Блоки лонгрида
|
||||
|
||||
| Класс | Назначение |
|
||||
|
||||
+108
-159
@@ -219,63 +219,7 @@
|
||||
|
||||
<link rel="stylesheet" href="/vendor/plyr/plyr.css" />
|
||||
|
||||
<style>
|
||||
/* Локальные правила страницы. Всё остальное — компоненты дизайн-системы:
|
||||
.contact-grid (сетка), .mp-card (карточка), .filter-chips (переключатель),
|
||||
.mp-card__tags/.mp-card__tag (метаданные), .case-links-grid (ссылки),
|
||||
.hero__tags/.hero__tag (список навыков). */
|
||||
.ai-page {
|
||||
max-width: 52rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ai-page h2 {
|
||||
margin: 2.25rem 0 0.85rem;
|
||||
font-size: clamp(1.15rem, 2vw, 1.35rem);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
.ai-page .section__prose {
|
||||
margin-bottom: 0.75rem;
|
||||
color: var(--text);
|
||||
}
|
||||
.ai-page a:not(.btn) {
|
||||
color: var(--accent);
|
||||
}
|
||||
/* Сетка проектов: контракт .contact-grid, но 2 колонки и шире минимальная
|
||||
колонка — карточкам нужен воздух. Сама сетка и её адаптив из системы. */
|
||||
.ai-projects {
|
||||
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
||||
margin-bottom: 0;
|
||||
}
|
||||
/* Обложка- заглушка внутри карточки. */
|
||||
.ai-projects__media {
|
||||
border-radius: var(--radius-sm);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
margin-bottom: 0.7rem;
|
||||
background: var(--bg-elevated);
|
||||
}
|
||||
.ai-projects__media img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 16 / 10;
|
||||
object-fit: cover;
|
||||
}
|
||||
/* Стек проекта — моноширинный, как .filter-chip__count в системе. */
|
||||
.ai-projects__stack {
|
||||
margin: 0;
|
||||
font-family: var(--font-mono, ui-monospace, monospace);
|
||||
font-size: 0.76rem;
|
||||
line-height: 1.4;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
/* У mp-card--compact теги уходят вниз карточки (order 2) — оставляем
|
||||
стек под заголовком, поэтому поднимаем его наравне с описанием. */
|
||||
.mp-card--compact .ai-projects__stack {
|
||||
order: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<a class="skip-link" href="#case-main">К содержимому кейса</a>
|
||||
@@ -374,47 +318,52 @@
|
||||
</div>
|
||||
|
||||
|
||||
<main id="case-main" class="section section--tight">
|
||||
<div class="section__inner ai-page">
|
||||
<p class="hero__eyebrow">AI-разработка · идея, код, деплой</p>
|
||||
<h1 class="case-page__h1">Делаю целые продукты</h1>
|
||||
<p class="case-page__sub">Telegram-боты, MCP-серверы, плагины и утилиты. Схема, код, деплой</p>
|
||||
<main id="case-main">
|
||||
<section class="section">
|
||||
<div class="section__inner hero__grid">
|
||||
<div>
|
||||
<p class="hero__eyebrow">AI-разработка · идея, код, деплой</p>
|
||||
<h1 class="hero__title">От идеи<br />до продукта.</h1>
|
||||
</div>
|
||||
<div>
|
||||
<p class="case-page__sub">Проектирую, собираю и запускаю цифровые продукты.</p>
|
||||
<p class="section__prose">
|
||||
Больше десяти лет я проектировал интерфейсы. Теперь отвечаю за весь путь:
|
||||
продуктовую логику, код, базу и инфраструктуру. Код часто пишет ИИ-агент.
|
||||
Архитектуру и результат проверяю я.
|
||||
</p>
|
||||
<ul class="hero__tags" aria-label="Что я делаю">
|
||||
<li class="hero__tag">Продуктовая логика и API</li>
|
||||
<li class="hero__tag">Telegram-боты</li>
|
||||
<li class="hero__tag">MCP-серверы</li>
|
||||
<li class="hero__tag">Плагины и автоматизация</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="section__prose">
|
||||
Больше десяти лет я проектировал интерфейсы. Теперь довожу идеи до работающего
|
||||
кода: бэкенд, база данных, деплой. Инфраструктура тоже моя часть работы.
|
||||
В большинстве проектов код пишет ИИ-агент. Я задаю архитектуру, проверяю
|
||||
результат и отвечаю за то, что продукт вообще работает.
|
||||
</p>
|
||||
|
||||
<h2 id="roles">Что я делаю</h2>
|
||||
<ul class="section__prose hero__tags" aria-label="Что я делаю">
|
||||
<li class="hero__tag">Продуктовая логика и API</li>
|
||||
<li class="hero__tag">Telegram-боты на aiogram 3</li>
|
||||
<li class="hero__tag">MCP-серверы</li>
|
||||
<li class="hero__tag">Плагины Figma и Obsidian</li>
|
||||
<li class="hero__tag">Автоматизация и агентные пайплайны</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="projects">Проекты</h2>
|
||||
<section class="section section--tight">
|
||||
<div class="section__inner">
|
||||
<p class="hero__eyebrow">01 / Сделано и запущено</p>
|
||||
<h2 id="projects" class="hero__title">Проекты</h2>
|
||||
<ul class="filter-chips" data-filter-chips data-filter-scope="#ai-projects" aria-label="Фильтр проектов по типу">
|
||||
<li><button type="button" class="filter-chip" data-filter-value="all" aria-pressed="true">Все</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Бots</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Боты</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="mcp" aria-pressed="false">MCP</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="plugins" aria-pressed="false">Плагины</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="web" aria-pressed="false">Веб</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="infra" aria-pressed="false">Инфраструктура</button></li>
|
||||
</ul>
|
||||
|
||||
<ol class="contact-grid ai-projects" id="ai-projects">
|
||||
<ol class="project-grid" id="ai-projects">
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Personal Assistant</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM в одном диалоге.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -423,13 +372,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Image Gen Bot</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Бот для генерации изображений: баланс, реферальная программа, админ-логи в отдельные топики супергруппы.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -438,13 +387,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="mcp bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">MCP Image Server</h3>
|
||||
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
|
||||
<p class="mp-card__desc">JavaScript · MCP · OpenRouter</p>
|
||||
<p class="mp-card__desc">Собственный MCP-сервер для генерации картинок. Подключается к агентам как инструмент.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">MCP</li>
|
||||
@@ -453,13 +402,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">AI assistant</h3>
|
||||
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
|
||||
<p class="mp-card__desc">TypeScript · Figma Plugin API</p>
|
||||
<p class="mp-card__desc">Плагин для Figma, который исполняет скрипты прямо в редакторе. ИИ-ассистент для любого тарифа.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -468,13 +417,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Card Columns</h3>
|
||||
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
|
||||
<p class="mp-card__desc">TypeScript · Obsidian API</p>
|
||||
<p class="mp-card__desc">Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами по тегам.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -483,13 +432,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Hermes Desktop Plugins</h3>
|
||||
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
|
||||
<p class="mp-card__desc">JavaScript · TypeScript · Electron</p>
|
||||
<p class="mp-card__desc">Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи и контроль трат.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -498,13 +447,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Social Post Writer</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · SQLite</p>
|
||||
<p class="mp-card__desc">Бот, который превращает тезисы в готовый пост под нужную площадку и тон, учитывая голос автора.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -513,13 +462,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="web">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">AI Design Assistant</h3>
|
||||
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
|
||||
<p class="mp-card__desc">HTML · CSS · GLSL · WebGL</p>
|
||||
<p class="mp-card__desc">Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD. Весь цикл создания вместе с ИИ-агентом.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Веб</li>
|
||||
@@ -528,13 +477,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Секреты и менеджер паролей</h3>
|
||||
<p class="ai-projects__stack">Vaultwarden · Docker · Coolify</p>
|
||||
<p class="mp-card__desc">Vaultwarden · Docker · Coolify</p>
|
||||
<p class="mp-card__desc">Своё хранилище паролей с веб-доступом. Отдельный сервис, доступ к API закрыт ключом.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -543,13 +492,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Прокси к хранилищу</h3>
|
||||
<p class="ai-projects__stack">Go · Vaultwarden API · all-cipher</p>
|
||||
<p class="mp-card__desc">Go · Vaultwarden API · all-cipher</p>
|
||||
<p class="mp-card__desc">Форк Vaultwarden API с поддержкой всех типов шифрования. Нужен, чтобы читать секреты из агентов и скиллов.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -558,13 +507,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Уведомления</h3>
|
||||
<p class="ai-projects__stack">Go · coturn · Matrix · ntfy</p>
|
||||
<p class="mp-card__desc">Go · coturn · Matrix · ntfy</p>
|
||||
<p class="mp-card__desc">Своя доставка уведомлений: ntfy для себя, Matrix-комната для агентов и WebRTC для звонков.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -573,13 +522,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="../assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Бот для новостей</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Telegram-бот, который присылает дайджест новостей по подпискам.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -589,49 +538,48 @@
|
||||
</article>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2 id="stack">Стек</h2>
|
||||
<ul class="section__prose hero__tags" aria-label="Стек">
|
||||
<li class="hero__tag">Python</li>
|
||||
<li class="hero__tag">TypeScript</li>
|
||||
<li class="hero__tag">JavaScript</li>
|
||||
<li class="hero__tag">Go</li>
|
||||
<li class="hero__tag">HTML/CSS</li>
|
||||
<li class="hero__tag">GLSL</li>
|
||||
<li class="hero__tag">aiogram 3</li>
|
||||
<li class="hero__tag">FastAPI</li>
|
||||
<li class="hero__tag">PostgreSQL</li>
|
||||
<li class="hero__tag">Redis</li>
|
||||
<li class="hero__tag">SQLite</li>
|
||||
<li class="hero__tag">Docker</li>
|
||||
<li class="hero__tag">Coolify</li>
|
||||
<li class="hero__tag">Gitea</li>
|
||||
<li class="hero__tag">MCP</li>
|
||||
</ul>
|
||||
<section class="section">
|
||||
<div class="section__inner hero__grid">
|
||||
<div>
|
||||
<p class="hero__eyebrow">02 / Среда, которую я собрал</p>
|
||||
<h2 id="infra" class="hero__title">Своя<br />инфраструктура.</h2>
|
||||
</div>
|
||||
<div>
|
||||
<p class="case-page__sub">Два VPS. Сервисы под моим контролем.</p>
|
||||
<p class="section__prose">
|
||||
Разворачиваю проекты в Docker через Coolify. Traefik ведёт домены и TLS;
|
||||
Gitea хранит код и запускает деплой. WireGuard соединяет серверы в закрытую
|
||||
сеть. PostgreSQL и Redis обслуживают ботов и приложения.
|
||||
</p>
|
||||
<ul class="hero__tags" aria-label="Инструменты инфраструктуры">
|
||||
<li class="hero__tag">Coolify</li>
|
||||
<li class="hero__tag">Traefik</li>
|
||||
<li class="hero__tag">Gitea</li>
|
||||
<li class="hero__tag">WireGuard</li>
|
||||
<li class="hero__tag">Docker</li>
|
||||
<li class="hero__tag">PostgreSQL</li>
|
||||
<li class="hero__tag">Redis</li>
|
||||
<li class="hero__tag">XRay</li>
|
||||
<li class="hero__tag">Python · aiogram</li>
|
||||
<li class="hero__tag">TypeScript · JavaScript</li>
|
||||
<li class="hero__tag">Go</li>
|
||||
<li class="hero__tag">GLSL · WebGL</li>
|
||||
</ul>
|
||||
<p class="section__prose">
|
||||
У сервисов отдельные схемы в общей базе. Между серверами ходит трафик
|
||||
через WireGuard, наружу открываются только нужные точки входа.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2 id="infra">Инфраструктура</h2>
|
||||
<p class="section__prose">
|
||||
Всё, что я делаю, живёт на двух VPS и не зависит от внешних PaaS. Деплой
|
||||
автоматический: пуш в ветку поднимает контейнер через Coolify, дальше
|
||||
реверс-прокси и TLS берёт на себя Traefik.
|
||||
</p>
|
||||
<ul class="mp-card__tags" aria-label="Состав инфраструктуры">
|
||||
<li class="mp-card__tag">Coolify · self-hosted панель деплоя</li>
|
||||
<li class="mp-card__tag">Traefik · прокси и сертификаты</li>
|
||||
<li class="mp-card__tag">Gitea · свой git и CI/CD</li>
|
||||
<li class="mp-card__tag">WireGuard · меш из нескольких серверов</li>
|
||||
<li class="mp-card__tag">XRay · VPN для доступа к API</li>
|
||||
<li class="mp-card__tag">Docker · изоляция сервисов</li>
|
||||
<li class="mp-card__tag">PostgreSQL · общая база по схемам</li>
|
||||
<li class="mp-card__tag">Redis · очереди и состояние FSM</li>
|
||||
</ul>
|
||||
<p class="section__prose">
|
||||
База одна на несколько проектов: каждый бот берёт свою схему, поэтому
|
||||
сервисы не мешают друг другу, но состояние видно целиком. Доступ между
|
||||
серверами закрыт WireGuard-туннелями, публичные адреса выдаёт Traefik.
|
||||
</p>
|
||||
|
||||
<h2 id="links">Где я это выкладываю</h2>
|
||||
<section class="section section--tight">
|
||||
<div class="section__inner">
|
||||
<p class="hero__eyebrow">03 / Код и проекты</p>
|
||||
<h2 id="links" class="case-page__h1">Смотреть дальше</h2>
|
||||
<ul class="case-links-grid">
|
||||
<li>
|
||||
<a class="case-link-card" href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">
|
||||
@@ -666,7 +614,8 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1053,6 +1053,15 @@
|
||||
</ul>
|
||||
<p class="sg-label">.filter-chips / .filter-chip[aria-pressed] + [data-filter-item][data-filter-tag]</p>
|
||||
|
||||
<h3>Сетка проектов</h3>
|
||||
<p class="section__prose">Адаптивная сетка карточек: одна колонка на узком экране, две от 680 px и три от 1120 px. Внутри списка используйте существующий компонент карточки.</p>
|
||||
<ul class="project-grid" aria-label="Демо сетки проектов">
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="../../assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект A</h3><p class="mp-card__desc">Карточка в адаптивной сетке.</p></div></article></li>
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="../../assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект B</h3><p class="mp-card__desc">Сетка подстраивается под экран.</p></div></article></li>
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="../../assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект C</h3><p class="mp-card__desc">Карточки сохраняют заданный ритм.</p></div></article></li>
|
||||
</ul>
|
||||
<p class="sg-label">.project-grid + .mp-card--stack</p>
|
||||
|
||||
<h3>Карточка портфолио</h3>
|
||||
<div class="sg-portfolio-wrap">
|
||||
<a class="mp-card mp-card--link mp-card--stack-bottom" href="#components" tabindex="-1" aria-hidden="true">
|
||||
|
||||
@@ -4709,6 +4709,32 @@ html[data-radius="strong"] .skill-task-card__solution {
|
||||
margin-top: 0.4rem;
|
||||
}
|
||||
|
||||
.project-grid {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: clamp(1.25rem, 2.5vw, 2.25rem);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
@media (min-width: 680px) {
|
||||
.project-grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1120px) {
|
||||
.project-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: clamp(1.5rem, 3vw, 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
.project-grid > li {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.contact-grid {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
|
||||
+108
-159
@@ -10,108 +10,57 @@
|
||||
<title>AI-разработка · Николай Мамадаев</title>
|
||||
{{> head-links}}
|
||||
{{> head-plyr}}
|
||||
<style>
|
||||
/* Локальные правила страницы. Всё остальное — компоненты дизайн-системы:
|
||||
.contact-grid (сетка), .mp-card (карточка), .filter-chips (переключатель),
|
||||
.mp-card__tags/.mp-card__tag (метаданные), .case-links-grid (ссылки),
|
||||
.hero__tags/.hero__tag (список навыков). */
|
||||
.ai-page {
|
||||
max-width: 52rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.ai-page h2 {
|
||||
margin: 2.25rem 0 0.85rem;
|
||||
font-size: clamp(1.15rem, 2vw, 1.35rem);
|
||||
font-weight: 700;
|
||||
color: var(--text);
|
||||
}
|
||||
.ai-page .section__prose {
|
||||
margin-bottom: 0.75rem;
|
||||
color: var(--text);
|
||||
}
|
||||
.ai-page a:not(.btn) {
|
||||
color: var(--accent);
|
||||
}
|
||||
/* Сетка проектов: контракт .contact-grid, но 2 колонки и шире минимальная
|
||||
колонка — карточкам нужен воздух. Сама сетка и её адаптив из системы. */
|
||||
.ai-projects {
|
||||
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
||||
margin-bottom: 0;
|
||||
}
|
||||
/* Обложка- заглушка внутри карточки. */
|
||||
.ai-projects__media {
|
||||
border-radius: var(--radius-sm);
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--line);
|
||||
margin-bottom: 0.7rem;
|
||||
background: var(--bg-elevated);
|
||||
}
|
||||
.ai-projects__media img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
aspect-ratio: 16 / 10;
|
||||
object-fit: cover;
|
||||
}
|
||||
/* Стек проекта — моноширинный, как .filter-chip__count в системе. */
|
||||
.ai-projects__stack {
|
||||
margin: 0;
|
||||
font-family: var(--font-mono, ui-monospace, monospace);
|
||||
font-size: 0.76rem;
|
||||
line-height: 1.4;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
/* У mp-card--compact теги уходят вниз карточки (order 2) — оставляем
|
||||
стек под заголовком, поэтому поднимаем его наравне с описанием. */
|
||||
.mp-card--compact .ai-projects__stack {
|
||||
order: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
{{> header-case}}
|
||||
{{> fab-stack}}
|
||||
<main id="case-main" class="section section--tight">
|
||||
<div class="section__inner ai-page">
|
||||
<p class="hero__eyebrow">AI-разработка · идея, код, деплой</p>
|
||||
<h1 class="case-page__h1">Делаю целые продукты</h1>
|
||||
<p class="case-page__sub">Telegram-боты, MCP-серверы, плагины и утилиты. Схема, код, деплой</p>
|
||||
<main id="case-main">
|
||||
<section class="section">
|
||||
<div class="section__inner hero__grid">
|
||||
<div>
|
||||
<p class="hero__eyebrow">AI-разработка · идея, код, деплой</p>
|
||||
<h1 class="hero__title">От идеи<br />до продукта.</h1>
|
||||
</div>
|
||||
<div>
|
||||
<p class="case-page__sub">Проектирую, собираю и запускаю цифровые продукты.</p>
|
||||
<p class="section__prose">
|
||||
Больше десяти лет я проектировал интерфейсы. Теперь отвечаю за весь путь:
|
||||
продуктовую логику, код, базу и инфраструктуру. Код часто пишет ИИ-агент.
|
||||
Архитектуру и результат проверяю я.
|
||||
</p>
|
||||
<ul class="hero__tags" aria-label="Что я делаю">
|
||||
<li class="hero__tag">Продуктовая логика и API</li>
|
||||
<li class="hero__tag">Telegram-боты</li>
|
||||
<li class="hero__tag">MCP-серверы</li>
|
||||
<li class="hero__tag">Плагины и автоматизация</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<p class="section__prose">
|
||||
Больше десяти лет я проектировал интерфейсы. Теперь довожу идеи до работающего
|
||||
кода: бэкенд, база данных, деплой. Инфраструктура тоже моя часть работы.
|
||||
В большинстве проектов код пишет ИИ-агент. Я задаю архитектуру, проверяю
|
||||
результат и отвечаю за то, что продукт вообще работает.
|
||||
</p>
|
||||
|
||||
<h2 id="roles">Что я делаю</h2>
|
||||
<ul class="section__prose hero__tags" aria-label="Что я делаю">
|
||||
<li class="hero__tag">Продуктовая логика и API</li>
|
||||
<li class="hero__tag">Telegram-боты на aiogram 3</li>
|
||||
<li class="hero__tag">MCP-серверы</li>
|
||||
<li class="hero__tag">Плагины Figma и Obsidian</li>
|
||||
<li class="hero__tag">Автоматизация и агентные пайплайны</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="projects">Проекты</h2>
|
||||
<section class="section section--tight">
|
||||
<div class="section__inner">
|
||||
<p class="hero__eyebrow">01 / Сделано и запущено</p>
|
||||
<h2 id="projects" class="hero__title">Проекты</h2>
|
||||
<ul class="filter-chips" data-filter-chips data-filter-scope="#ai-projects" aria-label="Фильтр проектов по типу">
|
||||
<li><button type="button" class="filter-chip" data-filter-value="all" aria-pressed="true">Все</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Бots</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Боты</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="mcp" aria-pressed="false">MCP</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="plugins" aria-pressed="false">Плагины</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="web" aria-pressed="false">Веб</button></li>
|
||||
<li><button type="button" class="filter-chip" data-filter-value="infra" aria-pressed="false">Инфраструктура</button></li>
|
||||
</ul>
|
||||
|
||||
<ol class="contact-grid ai-projects" id="ai-projects">
|
||||
<ol class="project-grid" id="ai-projects">
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Personal Assistant</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM в одном диалоге.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -120,13 +69,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Image Gen Bot</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Бот для генерации изображений: баланс, реферальная программа, админ-логи в отдельные топики супергруппы.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -135,13 +84,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="mcp bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">MCP Image Server</h3>
|
||||
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
|
||||
<p class="mp-card__desc">JavaScript · MCP · OpenRouter</p>
|
||||
<p class="mp-card__desc">Собственный MCP-сервер для генерации картинок. Подключается к агентам как инструмент.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">MCP</li>
|
||||
@@ -150,13 +99,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">AI assistant</h3>
|
||||
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
|
||||
<p class="mp-card__desc">TypeScript · Figma Plugin API</p>
|
||||
<p class="mp-card__desc">Плагин для Figma, который исполняет скрипты прямо в редакторе. ИИ-ассистент для любого тарифа.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -165,13 +114,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Card Columns</h3>
|
||||
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
|
||||
<p class="mp-card__desc">TypeScript · Obsidian API</p>
|
||||
<p class="mp-card__desc">Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами по тегам.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -180,13 +129,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="plugins">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Hermes Desktop Plugins</h3>
|
||||
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
|
||||
<p class="mp-card__desc">JavaScript · TypeScript · Electron</p>
|
||||
<p class="mp-card__desc">Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи и контроль трат.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Плагины</li>
|
||||
@@ -195,13 +144,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Social Post Writer</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · SQLite</p>
|
||||
<p class="mp-card__desc">Бот, который превращает тезисы в готовый пост под нужную площадку и тон, учитывая голос автора.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Боты</li>
|
||||
@@ -210,13 +159,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="web">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">AI Design Assistant</h3>
|
||||
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
|
||||
<p class="mp-card__desc">HTML · CSS · GLSL · WebGL</p>
|
||||
<p class="mp-card__desc">Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD. Весь цикл создания вместе с ИИ-агентом.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Веб</li>
|
||||
@@ -225,13 +174,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Секреты и менеджер паролей</h3>
|
||||
<p class="ai-projects__stack">Vaultwarden · Docker · Coolify</p>
|
||||
<p class="mp-card__desc">Vaultwarden · Docker · Coolify</p>
|
||||
<p class="mp-card__desc">Своё хранилище паролей с веб-доступом. Отдельный сервис, доступ к API закрыт ключом.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -240,13 +189,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Прокси к хранилищу</h3>
|
||||
<p class="ai-projects__stack">Go · Vaultwarden API · all-cipher</p>
|
||||
<p class="mp-card__desc">Go · Vaultwarden API · all-cipher</p>
|
||||
<p class="mp-card__desc">Форк Vaultwarden API с поддержкой всех типов шифрования. Нужен, чтобы читать секреты из агентов и скиллов.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -255,13 +204,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Уведомления</h3>
|
||||
<p class="ai-projects__stack">Go · coturn · Matrix · ntfy</p>
|
||||
<p class="mp-card__desc">Go · coturn · Matrix · ntfy</p>
|
||||
<p class="mp-card__desc">Своя доставка уведомлений: ntfy для себя, Matrix-комната для агентов и WebRTC для звонков.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -270,13 +219,13 @@
|
||||
</article>
|
||||
</li>
|
||||
<li data-filter-item data-filter-tag="infra bots">
|
||||
<article class="mp-card mp-card--compact" data-glass="false">
|
||||
<div class="mp-card__media ai-projects__media" aria-hidden="true">
|
||||
<article class="mp-card mp-card--stack" data-glass="false">
|
||||
<div class="mp-card__media" aria-hidden="true">
|
||||
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
|
||||
</div>
|
||||
<div class="mp-card__body">
|
||||
<h3 class="mp-card__title">Бот для новостей</h3>
|
||||
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Python · aiogram 3 · PostgreSQL</p>
|
||||
<p class="mp-card__desc">Telegram-бот, который присылает дайджест новостей по подпискам.</p>
|
||||
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||
<li class="mp-card__tag">Инфраструктура</li>
|
||||
@@ -286,49 +235,48 @@
|
||||
</article>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2 id="stack">Стек</h2>
|
||||
<ul class="section__prose hero__tags" aria-label="Стек">
|
||||
<li class="hero__tag">Python</li>
|
||||
<li class="hero__tag">TypeScript</li>
|
||||
<li class="hero__tag">JavaScript</li>
|
||||
<li class="hero__tag">Go</li>
|
||||
<li class="hero__tag">HTML/CSS</li>
|
||||
<li class="hero__tag">GLSL</li>
|
||||
<li class="hero__tag">aiogram 3</li>
|
||||
<li class="hero__tag">FastAPI</li>
|
||||
<li class="hero__tag">PostgreSQL</li>
|
||||
<li class="hero__tag">Redis</li>
|
||||
<li class="hero__tag">SQLite</li>
|
||||
<li class="hero__tag">Docker</li>
|
||||
<li class="hero__tag">Coolify</li>
|
||||
<li class="hero__tag">Gitea</li>
|
||||
<li class="hero__tag">MCP</li>
|
||||
</ul>
|
||||
<section class="section">
|
||||
<div class="section__inner hero__grid">
|
||||
<div>
|
||||
<p class="hero__eyebrow">02 / Среда, которую я собрал</p>
|
||||
<h2 id="infra" class="hero__title">Своя<br />инфраструктура.</h2>
|
||||
</div>
|
||||
<div>
|
||||
<p class="case-page__sub">Два VPS. Сервисы под моим контролем.</p>
|
||||
<p class="section__prose">
|
||||
Разворачиваю проекты в Docker через Coolify. Traefik ведёт домены и TLS;
|
||||
Gitea хранит код и запускает деплой. WireGuard соединяет серверы в закрытую
|
||||
сеть. PostgreSQL и Redis обслуживают ботов и приложения.
|
||||
</p>
|
||||
<ul class="hero__tags" aria-label="Инструменты инфраструктуры">
|
||||
<li class="hero__tag">Coolify</li>
|
||||
<li class="hero__tag">Traefik</li>
|
||||
<li class="hero__tag">Gitea</li>
|
||||
<li class="hero__tag">WireGuard</li>
|
||||
<li class="hero__tag">Docker</li>
|
||||
<li class="hero__tag">PostgreSQL</li>
|
||||
<li class="hero__tag">Redis</li>
|
||||
<li class="hero__tag">XRay</li>
|
||||
<li class="hero__tag">Python · aiogram</li>
|
||||
<li class="hero__tag">TypeScript · JavaScript</li>
|
||||
<li class="hero__tag">Go</li>
|
||||
<li class="hero__tag">GLSL · WebGL</li>
|
||||
</ul>
|
||||
<p class="section__prose">
|
||||
У сервисов отдельные схемы в общей базе. Между серверами ходит трафик
|
||||
через WireGuard, наружу открываются только нужные точки входа.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<h2 id="infra">Инфраструктура</h2>
|
||||
<p class="section__prose">
|
||||
Всё, что я делаю, живёт на двух VPS и не зависит от внешних PaaS. Деплой
|
||||
автоматический: пуш в ветку поднимает контейнер через Coolify, дальше
|
||||
реверс-прокси и TLS берёт на себя Traefik.
|
||||
</p>
|
||||
<ul class="mp-card__tags" aria-label="Состав инфраструктуры">
|
||||
<li class="mp-card__tag">Coolify · self-hosted панель деплоя</li>
|
||||
<li class="mp-card__tag">Traefik · прокси и сертификаты</li>
|
||||
<li class="mp-card__tag">Gitea · свой git и CI/CD</li>
|
||||
<li class="mp-card__tag">WireGuard · меш из нескольких серверов</li>
|
||||
<li class="mp-card__tag">XRay · VPN для доступа к API</li>
|
||||
<li class="mp-card__tag">Docker · изоляция сервисов</li>
|
||||
<li class="mp-card__tag">PostgreSQL · общая база по схемам</li>
|
||||
<li class="mp-card__tag">Redis · очереди и состояние FSM</li>
|
||||
</ul>
|
||||
<p class="section__prose">
|
||||
База одна на несколько проектов: каждый бот берёт свою схему, поэтому
|
||||
сервисы не мешают друг другу, но состояние видно целиком. Доступ между
|
||||
серверами закрыт WireGuard-туннелями, публичные адреса выдаёт Traefik.
|
||||
</p>
|
||||
|
||||
<h2 id="links">Где я это выкладываю</h2>
|
||||
<section class="section section--tight">
|
||||
<div class="section__inner">
|
||||
<p class="hero__eyebrow">03 / Код и проекты</p>
|
||||
<h2 id="links" class="case-page__h1">Смотреть дальше</h2>
|
||||
<ul class="case-links-grid">
|
||||
<li>
|
||||
<a class="case-link-card" href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">
|
||||
@@ -363,7 +311,8 @@
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -744,6 +744,15 @@
|
||||
</ul>
|
||||
<p class="sg-label">.filter-chips / .filter-chip[aria-pressed] + [data-filter-item][data-filter-tag]</p>
|
||||
|
||||
<h3>Сетка проектов</h3>
|
||||
<p class="section__prose">Адаптивная сетка карточек: одна колонка на узком экране, две от 680 px и три от 1120 px. Внутри списка используйте существующий компонент карточки.</p>
|
||||
<ul class="project-grid" aria-label="Демо сетки проектов">
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="{{assetPrefix}}assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект A</h3><p class="mp-card__desc">Карточка в адаптивной сетке.</p></div></article></li>
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="{{assetPrefix}}assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект B</h3><p class="mp-card__desc">Сетка подстраивается под экран.</p></div></article></li>
|
||||
<li><article class="mp-card mp-card--stack" data-glass="false"><div class="mp-card__media" aria-hidden="true"><img class="mp-card__image" src="{{assetPrefix}}assets/shared/placeholder.webp" alt="" width="400" height="225" loading="lazy" decoding="async" /></div><div class="mp-card__body"><h3 class="mp-card__title">Проект C</h3><p class="mp-card__desc">Карточки сохраняют заданный ритм.</p></div></article></li>
|
||||
</ul>
|
||||
<p class="sg-label">.project-grid + .mp-card--stack</p>
|
||||
|
||||
<h3>Карточка портфолио</h3>
|
||||
<div class="sg-portfolio-wrap">
|
||||
<a class="mp-card mp-card--link mp-card--stack-bottom" href="#components" tabindex="-1" aria-hidden="true">
|
||||
|
||||
Reference in new issue
Block a user