feat: страница /ai-dev/ — AI-разработка и проекты, карточка в Активности
This commit is contained in:
1 parent
39dad71bd1
commit
52485a17c4
10 files changed
+1089
-4
No files matched your search
@@ -0,0 +1,653 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru" data-theme="dark" data-radius="medium">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты."
|
||||||
|
/>
|
||||||
|
<title>AI-разработка · Николай Мамадаев</title>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var FONT_CSS = {
|
||||||
|
merriweather: "/assets/fonts/merriweather.css",
|
||||||
|
geologica: "/assets/fonts/geologica.css",
|
||||||
|
mono: "/assets/fonts/mono.css",
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
var t = JSON.parse(localStorage.getItem("siteThemeV1") || "{}");
|
||||||
|
var d = document.documentElement;
|
||||||
|
var m = t.mode;
|
||||||
|
if (m !== "light" && m !== "dark" && m !== "system") m = "system";
|
||||||
|
var eff =
|
||||||
|
m === "system"
|
||||||
|
? window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches
|
||||||
|
? "dark"
|
||||||
|
: "light"
|
||||||
|
: m;
|
||||||
|
d.dataset.theme = eff;
|
||||||
|
var DEF = { h: 210, s: 90, l: 40 };
|
||||||
|
function pickAccent(o) {
|
||||||
|
if (!o) return null;
|
||||||
|
var h = typeof o.h === "number" ? o.h : typeof o.hue === "number" ? o.hue : null;
|
||||||
|
var s = typeof o.s === "number" ? o.s : typeof o.sat === "number" ? o.sat : null;
|
||||||
|
var l = typeof o.l === "number" ? o.l : typeof o.light === "number" ? o.light : null;
|
||||||
|
if (h === null && s === null && l === null) return null;
|
||||||
|
return {
|
||||||
|
h: h === null ? DEF.h : h,
|
||||||
|
s: s === null ? DEF.s : Math.min(100, Math.max(30, s)),
|
||||||
|
l: l === null ? DEF.l : Math.min(70, Math.max(20, l)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// Текущий формат: отдельный акцент для светлой и тёмной темы ({light, dark}).
|
||||||
|
// Старый плоский формат ({h, s, l}) остаётся совместимым.
|
||||||
|
var acc =
|
||||||
|
pickAccent(eff === "dark" ? t.dark : t.light) ||
|
||||||
|
pickAccent(eff === "dark" ? t.light : t.dark) ||
|
||||||
|
pickAccent(t) ||
|
||||||
|
DEF;
|
||||||
|
d.style.setProperty("--theme-h", String(acc.h));
|
||||||
|
d.style.setProperty("--theme-s", String(acc.s));
|
||||||
|
d.style.setProperty("--theme-l", String(acc.l));
|
||||||
|
var H = (((acc.h % 360) + 360) % 360) / 360;
|
||||||
|
var S = Math.min(100, Math.max(0, acc.s)) / 100;
|
||||||
|
var Lv = Math.min(100, Math.max(0, acc.l)) / 100;
|
||||||
|
var r, g, b;
|
||||||
|
if (S === 0) { r = g = b = Lv; }
|
||||||
|
else {
|
||||||
|
var q = Lv < 0.5 ? Lv * (1 + S) : Lv + S - Lv * S;
|
||||||
|
var p = 2 * Lv - q;
|
||||||
|
var hue2rgb = function(p, q, t) {
|
||||||
|
if (t < 0) t += 1; if (t > 1) t -= 1;
|
||||||
|
if (t < 1/6) return p + (q - p) * 6 * t;
|
||||||
|
if (t < 1/2) return q;
|
||||||
|
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
r = hue2rgb(p, q, H + 1/3);
|
||||||
|
g = hue2rgb(p, q, H);
|
||||||
|
b = hue2rgb(p, q, H - 1/3);
|
||||||
|
}
|
||||||
|
var lum = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||||
|
d.style.setProperty("--on-accent", lum > 0.58 ? "hsl(220 14% 12%)" : "hsl(0 0% 98%)");
|
||||||
|
var rad = t.radius;
|
||||||
|
if (rad === "soft" || rad === "medium" || rad === "strong") {
|
||||||
|
d.dataset.radius = rad;
|
||||||
|
} else {
|
||||||
|
d.dataset.radius = "medium";
|
||||||
|
}
|
||||||
|
var f = t.font;
|
||||||
|
if (f === "onest") f = "geologica";
|
||||||
|
if (f === "anonymous") f = "mono";
|
||||||
|
if (f !== "merriweather" && f !== "mono" && f !== "geologica") f = "geologica";
|
||||||
|
d.dataset.font = f;
|
||||||
|
var mb = t.meshBg;
|
||||||
|
if (mb === "off") {
|
||||||
|
d.dataset.meshBg = "off";
|
||||||
|
} else {
|
||||||
|
d.dataset.meshBg = "on";
|
||||||
|
}
|
||||||
|
var href = FONT_CSS[f];
|
||||||
|
if (href && !document.querySelector('link[data-theme-font="' + f + '"]')) {
|
||||||
|
var link = document.createElement("link");
|
||||||
|
link.rel = "stylesheet";
|
||||||
|
link.href = href;
|
||||||
|
link.setAttribute("data-theme-font", f);
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/assets/favicon/favicon-32x32.png" />
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/assets/favicon/favicon-16x16.png" />
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon.png" />
|
||||||
|
<link rel="manifest" href="/assets/favicon/site.webmanifest" />
|
||||||
|
<link rel="preload" href="/assets/fonts/merriweather.css" as="style" />
|
||||||
|
<link rel="preload" href="/css/main.css" as="style" />
|
||||||
|
<link rel="preload" href="/js/skill-connectors.js" as="script" />
|
||||||
|
<link rel="modulepreload" href="/js/main.js" />
|
||||||
|
<link rel="modulepreload" href="/js/modules/ui/page-mesh-shader.js" />
|
||||||
|
<link rel="stylesheet" href="/css/main.css" />
|
||||||
|
<link rel="canonical" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<link rel="alternate" hreflang="ru" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<link rel="alternate" hreflang="en" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<link rel="alternate" hreflang="x-default" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<meta name="author" content="Николай Мамадаев" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta name="theme-color" content="#0f1115" />
|
||||||
|
|
||||||
|
<!-- Open Graph -->
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:site_name" content="Николай Мамадаев — продуктовый дизайнер" />
|
||||||
|
<meta property="og:locale" content="ru_RU" />
|
||||||
|
<meta property="og:locale:alternate" content="en_US" />
|
||||||
|
<meta property="og:title" content="AI-разработка · Николай Мамадаев" />
|
||||||
|
<meta property="og:description" content="Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты." />
|
||||||
|
<meta property="og:url" content="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<meta property="og:image" content="https://mamadaevv.site/assets/og/og-default.png" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta property="og:image:alt" content="AI-разработка · Николай Мамадаев" />
|
||||||
|
|
||||||
|
<!-- Twitter / X -->
|
||||||
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
|
<meta name="twitter:title" content="AI-разработка · Николай Мамадаев" />
|
||||||
|
<meta name="twitter:description" content="Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты." />
|
||||||
|
<meta name="twitter:image" content="https://mamadaevv.site/assets/og/og-default.png" />
|
||||||
|
<meta name="twitter:image:alt" content="AI-разработка · Николай Мамадаев" />
|
||||||
|
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@graph": [
|
||||||
|
{
|
||||||
|
"@type": "Person",
|
||||||
|
"@id": "https://mamadaevv.site/#person",
|
||||||
|
"name": "Николай Мамадаев",
|
||||||
|
"url": "https://mamadaevv.site",
|
||||||
|
"jobTitle": "Продуктовый дизайнер",
|
||||||
|
"description": "Продуктовый дизайнер с опытом более 10 лет. Проектирую цифровые продукты, интерфейсы и дизайн-системы.",
|
||||||
|
"knowsAbout": [
|
||||||
|
"UX/UI-дизайн",
|
||||||
|
"продуктовый дизайн",
|
||||||
|
"дизайн-системы",
|
||||||
|
"прототипирование",
|
||||||
|
"Figma",
|
||||||
|
"no-code"
|
||||||
|
],
|
||||||
|
"sameAs": [
|
||||||
|
"https://t.me/mamadaevv",
|
||||||
|
"https://vk.com/mamadaevv",
|
||||||
|
"https://github.com/mamadaevv"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "WebSite",
|
||||||
|
"@id": "https://mamadaevv.site/#website",
|
||||||
|
"url": "https://mamadaevv.site/",
|
||||||
|
"name": "Николай Мамадаев — продуктовый дизайнер",
|
||||||
|
"inLanguage": "ru",
|
||||||
|
"author": {
|
||||||
|
"@id": "https://mamadaevv.site/#person"
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@id": "https://mamadaevv.site/#person"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "WebPage",
|
||||||
|
"@id": "https://mamadaevv.site/ai-dev/#page",
|
||||||
|
"url": "https://mamadaevv.site/ai-dev/",
|
||||||
|
"name": "AI-разработка · Николай Мамадаев",
|
||||||
|
"description": "Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты.",
|
||||||
|
"isPartOf": {
|
||||||
|
"@id": "https://mamadaevv.site/#website"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"@id": "https://mamadaevv.site/#person"
|
||||||
|
},
|
||||||
|
"inLanguage": "ru"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "BreadcrumbList",
|
||||||
|
"@id": "https://mamadaevv.site/ai-dev/#breadcrumbs",
|
||||||
|
"itemListElement": [
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 1,
|
||||||
|
"name": "Николай Мамадаев — продуктовый дизайнер",
|
||||||
|
"item": "https://mamadaevv.site/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"@type": "ListItem",
|
||||||
|
"position": 2,
|
||||||
|
"name": "AI-разработка · Николай Мамадаев",
|
||||||
|
"item": "https://mamadaevv.site/ai-dev/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="/js/skill-connectors.js" defer></script>
|
||||||
|
<script type="module" src="/js/main.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/vendor/plyr/plyr.css" />
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
/* Сетка карточек проектов: 2 колонки, схлопывается в одну на мобильном */
|
||||||
|
.ai-projects {
|
||||||
|
list-style: none;
|
||||||
|
margin: 1.25rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.ai-projects > li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.ai-projects__media {
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
.ai-projects__media img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 16 / 10;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.ai-projects__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.ai-projects__title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.ai-projects__stack {
|
||||||
|
margin: 0.3rem 0 0;
|
||||||
|
font-family: var(--font-mono, ui-monospace, monospace);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
.ai-projects__desc {
|
||||||
|
margin: 0.45rem 0 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.ai-projects__links {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0.6rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.4rem 0.9rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
/* Навыки — компактные чипы переиспользуют стили тегов карточек активности */
|
||||||
|
.ai-stack-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 1rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.45rem;
|
||||||
|
}
|
||||||
|
.ai-stack-list li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 999px;
|
||||||
|
font-family: var(--font-mono, ui-monospace, monospace);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a class="skip-link" href="#case-main">К содержимому кейса</a>
|
||||||
|
<header class="header" data-theme-picker>
|
||||||
|
<div class="header__inner">
|
||||||
|
<a class="logo" href="../" aria-label="На главную">НМ</a>
|
||||||
|
<div class="header__cluster">
|
||||||
|
<nav class="nav" aria-label="Разделы страницы">
|
||||||
|
<a href="#contact">Контакты</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="fab-stack" aria-label="Быстрые действия">
|
||||||
|
<div class="theme-panel-fab-wrap">
|
||||||
|
<button type="button" class="fab fab--secondary glass-neutral" data-theme-panel-btn aria-expanded="false" aria-controls="theme-panel" aria-label="Настройки стиля">
|
||||||
|
<span class="theme-panel-fab__icon theme-panel-fab__icon--open-hide" aria-hidden="true"></span>
|
||||||
|
<svg class="theme-panel-fab__icon theme-panel-fab__icon--close" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||||
|
<path d="M6 6L18 18M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<div id="theme-panel" class="theme-picker__panel glass-neutral" role="dialog" aria-label="Тема и оформление" hidden data-theme-panel>
|
||||||
|
<div class="theme-picker__stack">
|
||||||
|
<section class="theme-picker__section" aria-labelledby="theme-accent-title">
|
||||||
|
<h3 id="theme-accent-title" class="theme-picker__section-title">Акцентный цвет</h3>
|
||||||
|
<div class="colorpicker" data-colorpicker>
|
||||||
|
<div class="colorpicker__plane-box">
|
||||||
|
<canvas class="colorpicker__plane" width="320" height="180" data-sl-canvas aria-label="Насыщенность и светлость акцента"></canvas>
|
||||||
|
<div class="colorpicker__knob" data-sl-knob></div>
|
||||||
|
</div>
|
||||||
|
<div class="colorpicker__hue-wrap">
|
||||||
|
<label class="colorpicker__hue-sr" for="theme-hue-slider">Оттенок акцента</label>
|
||||||
|
<input id="theme-hue-slider" class="colorpicker__hue" type="range" min="0" max="360" value="210" data-hue-slider aria-valuemin="0" aria-valuemax="360" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="theme-picker__section" aria-labelledby="theme-mode-title">
|
||||||
|
<h3 id="theme-mode-title" class="theme-picker__section-title">Тема</h3>
|
||||||
|
<div class="radius-seg theme-mode-seg" role="radiogroup" aria-labelledby="theme-mode-title">
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="system" aria-label="Как в системе"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--system"></span></span></button>
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="light" aria-label="Светлая тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--light"></span></span></button>
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-theme-mode="dark" aria-label="Тёмная тема"><span class="radius-seg__viz" aria-hidden="true"><span class="theme-mode-seg__ico theme-mode-seg__ico--dark"></span></span></button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="theme-picker__section" aria-labelledby="theme-radius-title">
|
||||||
|
<h3 id="theme-radius-title" class="theme-picker__section-title">Скругление углов</h3>
|
||||||
|
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-radius-title">
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="soft" aria-label="Слабое скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--soft"></span></span></button>
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="medium" aria-label="Среднее скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--medium"></span></span></button>
|
||||||
|
<button type="button" class="radius-seg__btn" role="radio" aria-checked="false" data-radius-option="strong" aria-label="Сильное скругление"><span class="radius-seg__viz" aria-hidden="true"><span class="radius-seg__arc radius-seg__arc--strong"></span></span></button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="theme-picker__section" aria-labelledby="theme-typography-title">
|
||||||
|
<h3 id="theme-typography-title" class="theme-picker__section-title">Типографика</h3>
|
||||||
|
<div class="radius-seg" role="radiogroup" aria-labelledby="theme-typography-title">
|
||||||
|
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="geologica" aria-label="Sans"><span class="theme-font-seg__label">Sans</span></button>
|
||||||
|
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="merriweather" aria-label="Sans Serif"><span class="theme-font-seg__label">Sans Serif</span></button>
|
||||||
|
<button type="button" class="radius-seg__btn theme-font-seg__btn" role="radio" aria-checked="false" data-font-option="mono" aria-label="Mono"><span class="theme-font-seg__label">Mono</span></button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="theme-picker__section" aria-labelledby="theme-mesh-bg-title">
|
||||||
|
<h3 id="theme-mesh-bg-title" class="theme-picker__section-title">Фон страницы</h3>
|
||||||
|
<div class="radius-seg radius-seg--two" role="radiogroup" aria-labelledby="theme-mesh-bg-title">
|
||||||
|
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="on" aria-label="Показать фоновый градиент"><span class="theme-mesh-bg-seg__label">Вкл</span></button>
|
||||||
|
<button type="button" class="radius-seg__btn theme-mesh-bg-seg__btn" role="radio" aria-checked="false" data-mesh-bg-option="off" aria-label="Скрыть фоновый градиент"><span class="theme-mesh-bg-seg__label">Выкл</span></button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="fab fab--primary" href="#contact" aria-label="Связаться">
|
||||||
|
<span class="fab-primary__ico" aria-hidden="true"></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="content-edit-fab-stack" aria-label="Правки контента" data-content-edit-ui>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="fab fab--secondary glass-neutral content-edit-fab"
|
||||||
|
data-content-edit-mode-toggle
|
||||||
|
hidden
|
||||||
|
aria-pressed="false"
|
||||||
|
aria-label="Режим правок контента"
|
||||||
|
title="Режим правок"
|
||||||
|
>
|
||||||
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
|
<path
|
||||||
|
d="M4 20h4l10.5-10.5a2.12 2.12 0 0 0 0-3L16.5 4.5a2.12 2.12 0 0 0-3 0L3 15v5z"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="1.75"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<span class="content-edit-fab__badge" hidden aria-hidden="true">0</span>
|
||||||
|
</button>
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<p class="section__prose">
|
||||||
|
Больше десяти лет я проектировал интерфейсы. Теперь довожу идеи до работающего
|
||||||
|
кода: бэкенд, база данных, деплой. Инфраструктура тоже моя часть работы.
|
||||||
|
В большинстве проектов код пишет ИИ-агент. Я задаю архитектуру, проверяю
|
||||||
|
результат и отвечаю за то, что продукт вообще работает.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="roles">Что я делаю</h2>
|
||||||
|
<ul class="section__prose ai-stack-list">
|
||||||
|
<li>Продуктовая логика и API</li>
|
||||||
|
<li>Telegram-боты на aiogram 3</li>
|
||||||
|
<li>MCP-серверы</li>
|
||||||
|
<li>Плагины Figma и Obsidian</li>
|
||||||
|
<li>Автоматизация и агентные пайплайны</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="projects">Проекты</h2>
|
||||||
|
<ol class="ai-projects">
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Personal Assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM
|
||||||
|
в одном диалоге.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="../cases/ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Image Gen Bot</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Бот для генерации изображений: баланс, реферальная программа, админ-логи
|
||||||
|
в отдельные топики супергруппы.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="../cases/ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-03.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">MCP Image Server</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Собственный MCP-сервер для генерации картинок. Подключается к агентам
|
||||||
|
как инструмент.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/mcp-img-gen" target="_blank" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">AI assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Плагин для Figma, который исполняет скрипты прямо в редакторе.
|
||||||
|
ИИ-ассистент для любого тарифа.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="../cases/ai-assistant-figma/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Card Columns</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами
|
||||||
|
по тегам.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="../cases/card-columns-obsidian/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-03.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Hermes Desktop Plugins</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи
|
||||||
|
и контроль трат.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/unorouter-balance" target="_blank" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Social Post Writer</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Бот, который превращает тезисы в готовый пост под нужную площадку и тон,
|
||||||
|
учитывая голос автора.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/social-post-writer-bot" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="../assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">AI Design Assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD.
|
||||||
|
Весь цикл создания вместе с ИИ-агентом.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="../cases/site-portfolio/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2 id="stack">Стек</h2>
|
||||||
|
<ul class="section__prose ai-stack-list">
|
||||||
|
<li>Python</li>
|
||||||
|
<li>TypeScript</li>
|
||||||
|
<li>JavaScript</li>
|
||||||
|
<li>Go</li>
|
||||||
|
<li>HTML/CSS</li>
|
||||||
|
<li>GLSL</li>
|
||||||
|
<li>aiogram 3</li>
|
||||||
|
<li>FastAPI</li>
|
||||||
|
<li>PostgreSQL</li>
|
||||||
|
<li>Redis</li>
|
||||||
|
<li>SQLite</li>
|
||||||
|
<li>Docker</li>
|
||||||
|
<li>Coolify</li>
|
||||||
|
<li>Gitea</li>
|
||||||
|
<li>MCP</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="links">Где я это выкладываю</h2>
|
||||||
|
<p class="section__prose">
|
||||||
|
Код открыт: <a href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">GitHub</a>
|
||||||
|
и <a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin" target="_blank" rel="noopener noreferrer">Gitea</a>.
|
||||||
|
Сервисы, которые работают прямо сейчас, живут на
|
||||||
|
<a href="https://secrets-4-me.dynv6.net" target="_blank" rel="noopener noreferrer">secrets-4-me</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 594 B |
Binary file not shown.
|
After Width: | Height: | Size: 526 B |
Binary file not shown.
|
After Width: | Height: | Size: 594 B |
@@ -838,6 +838,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ol id="mini-projects-list" class="mini-projects-grid" data-mini-projects-list>
|
<ol id="mini-projects-list" class="mini-projects-grid" data-mini-projects-list>
|
||||||
|
<li class="mini-projects-grid__item" data-mp-cells="2">
|
||||||
|
<a
|
||||||
|
class="mp-card mp-card--link mp-card--compact"
|
||||||
|
href="ai-dev/"
|
||||||
|
data-glass="false"
|
||||||
|
aria-label="AI-разработка — открыть страницу"
|
||||||
|
>
|
||||||
|
<div class="mp-card__body">
|
||||||
|
<h3 class="mp-card__title">AI-разработка</h3>
|
||||||
|
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||||
|
<li class="mp-card__tag">Боты · MCP · плагины</li>
|
||||||
|
</ul>
|
||||||
|
<p class="mp-card__desc">Не только дизайн, а целые продукты: от API до деплоя</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="mini-projects-grid__item" data-mp-cells="2">
|
<li class="mini-projects-grid__item" data-mp-cells="2">
|
||||||
<a
|
<a
|
||||||
class="mp-card mp-card--link mp-card--compact"
|
class="mp-card mp-card--link mp-card--compact"
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||||
|
<url>
|
||||||
|
<loc>https://mamadaevv.site/ai-dev/</loc>
|
||||||
|
<lastmod>2026-10-07</lastmod>
|
||||||
|
<xhtml:link rel="alternate" hreflang="x-default" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
<xhtml:link rel="alternate" hreflang="ru" href="https://mamadaevv.site/ai-dev/" />
|
||||||
|
</url>
|
||||||
<url>
|
<url>
|
||||||
<loc>https://mamadaevv.site/cases/ai-assistant-figma/</loc>
|
<loc>https://mamadaevv.site/cases/ai-assistant-figma/</loc>
|
||||||
<lastmod>2026-09-26</lastmod>
|
<lastmod>2026-09-26</lastmod>
|
||||||
|
|||||||
+15
-4
@@ -28,7 +28,7 @@ const NOINDEX_PAGES = new Set([
|
|||||||
|
|
||||||
// Страницы, у которых пока нет перевода: собираются только в дефолтную локаль,
|
// Страницы, у которых пока нет перевода: собираются только в дефолтную локаль,
|
||||||
// чтобы /en/ не отдавал русскоязычный дубль и не попадал в sitemap.
|
// чтобы /en/ не отдавал русскоязычный дубль и не попадал в sitemap.
|
||||||
const DEFAULT_LOCALE_ONLY_PAGES = new Set();
|
const DEFAULT_LOCALE_ONLY_PAGES = new Set(["ai-dev"]);
|
||||||
|
|
||||||
// Своя og-картинка для страницы основного AI Server-кейса.
|
// Своя og-картинка для страницы основного AI Server-кейса.
|
||||||
const PER_PAGE_OG_IMAGE = {
|
const PER_PAGE_OG_IMAGE = {
|
||||||
@@ -65,8 +65,9 @@ function sitePath(relNorm, loc) {
|
|||||||
const norm = relNorm.startsWith("cases/")
|
const norm = relNorm.startsWith("cases/")
|
||||||
? `cases/${path.basename(relNorm, ".html")}/`
|
? `cases/${path.basename(relNorm, ".html")}/`
|
||||||
: base === "resume" ? "resume/"
|
: base === "resume" ? "resume/"
|
||||||
: base === "cookie-policy" ? "cookie-policy/"
|
: base === "cookie-policy" ? "cookie-policy/"
|
||||||
: base === "" || base === "/" ? ""
|
: base === "ai-dev" ? "ai-dev/"
|
||||||
|
: base === "" || base === "/" ? ""
|
||||||
: `${base.replace(/\/$/, "")}/`;
|
: `${base.replace(/\/$/, "")}/`;
|
||||||
return loc === DEFAULT_LOCALE ? norm : `${loc}/${norm}`;
|
return loc === DEFAULT_LOCALE ? norm : `${loc}/${norm}`;
|
||||||
}
|
}
|
||||||
@@ -321,6 +322,9 @@ function baseVars(relNorm, depth) {
|
|||||||
if (relNorm === "cookie-policy.html") {
|
if (relNorm === "cookie-policy.html") {
|
||||||
return { assetPrefix: "../", casesPrefix: "" };
|
return { assetPrefix: "../", casesPrefix: "" };
|
||||||
}
|
}
|
||||||
|
if (relNorm === "ai-dev.html") {
|
||||||
|
return { assetPrefix: "../", casesPrefix: "../cases/" };
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
assetPrefix: depth === 0 ? "" : "../".repeat(depth),
|
assetPrefix: depth === 0 ? "" : "../".repeat(depth),
|
||||||
casesPrefix: depth === 0 ? "cases/" : "",
|
casesPrefix: depth === 0 ? "cases/" : "",
|
||||||
@@ -342,6 +346,7 @@ function build() {
|
|||||||
const isCase = relNorm.startsWith("cases/");
|
const isCase = relNorm.startsWith("cases/");
|
||||||
const isResume = relNorm === "resume.html";
|
const isResume = relNorm === "resume.html";
|
||||||
const isCookiePolicy = relNorm === "cookie-policy.html";
|
const isCookiePolicy = relNorm === "cookie-policy.html";
|
||||||
|
const isAiDev = relNorm === "ai-dev.html";
|
||||||
const omitFile = isCase ? path.basename(pagePath) : null;
|
const omitFile = isCase ? path.basename(pagePath) : null;
|
||||||
const noSlug = relNorm.replace(/\.html$/, "");
|
const noSlug = relNorm.replace(/\.html$/, "");
|
||||||
|
|
||||||
@@ -370,7 +375,11 @@ function build() {
|
|||||||
const vars = baseVars(relNorm, depth);
|
const vars = baseVars(relNorm, depth);
|
||||||
vars.canonicalUrl = canonicalUrl;
|
vars.canonicalUrl = canonicalUrl;
|
||||||
vars.canonicalRu = canonicalFor(relNorm, "ru");
|
vars.canonicalRu = canonicalFor(relNorm, "ru");
|
||||||
vars.canonicalEn = canonicalFor(relNorm, "en");
|
// Для ru-only страниц en-альтернаты не существует — отдаём ru,
|
||||||
|
// иначе hreflang указывает на несуществующий /en/... URL.
|
||||||
|
vars.canonicalEn = DEFAULT_LOCALE_ONLY_PAGES.has(noSlug)
|
||||||
|
? vars.canonicalRu
|
||||||
|
: canonicalFor(relNorm, "en");
|
||||||
vars.authorName = isDefault ? AUTHOR_NAME_RU : AUTHOR_NAME_EN;
|
vars.authorName = isDefault ? AUTHOR_NAME_RU : AUTHOR_NAME_EN;
|
||||||
vars.siteName = isDefault ? SITE_NAME_RU : SITE_NAME_EN;
|
vars.siteName = isDefault ? SITE_NAME_RU : SITE_NAME_EN;
|
||||||
vars.metaRobots = isNoindex ? "noindex, nofollow" : "index, follow";
|
vars.metaRobots = isNoindex ? "noindex, nofollow" : "index, follow";
|
||||||
@@ -403,6 +412,8 @@ function build() {
|
|||||||
outPath = path.join(outDir, langPrefix, "resume", "index.html");
|
outPath = path.join(outDir, langPrefix, "resume", "index.html");
|
||||||
} else if (isCookiePolicy) {
|
} else if (isCookiePolicy) {
|
||||||
outPath = path.join(outDir, langPrefix, "cookie-policy", "index.html");
|
outPath = path.join(outDir, langPrefix, "cookie-policy", "index.html");
|
||||||
|
} else if (isAiDev) {
|
||||||
|
outPath = path.join(outDir, langPrefix, "ai-dev", "index.html");
|
||||||
} else {
|
} else {
|
||||||
outPath = path.join(outDir, langPrefix, rel);
|
outPath = path.join(outDir, langPrefix, rel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// Генерация серых заглушек (16:10) для страницы ai-dev.
|
||||||
|
// Заглушки — намеренно нейтральный серый, без текста и градиентов.
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import sharp from "sharp";
|
||||||
|
|
||||||
|
const outDir = path.join(process.cwd(), "public", "assets", "ai-dev");
|
||||||
|
fs.mkdirSync(outDir, { recursive: true });
|
||||||
|
|
||||||
|
const W = 640;
|
||||||
|
const H = 400;
|
||||||
|
|
||||||
|
// Разные оттенки серого, чтобы карточки не выглядели одинаковыми при загрузке.
|
||||||
|
const shades = [
|
||||||
|
{ fill: "#2a2d31", label: "01" },
|
||||||
|
{ fill: "#31353a", label: "02" },
|
||||||
|
{ fill: "#25282c", label: "03" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const tiles = await Promise.all(
|
||||||
|
shades.map(async ({ fill, label }) => {
|
||||||
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}">
|
||||||
|
<rect width="${W}" height="${H}" fill="${fill}" />
|
||||||
|
</svg>`;
|
||||||
|
const file = path.join(outDir, `placeholder-${label}.webp`);
|
||||||
|
await sharp(Buffer.from(svg)).webp({ quality: 72 }).toFile(file);
|
||||||
|
return file;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`Generated ${tiles.length} placeholders in ${outDir}`);
|
||||||
|
for (const f of tiles) console.log(" ", path.basename(f), fs.statSync(f).size, "bytes");
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru" data-theme="dark" data-radius="medium">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||||||
|
<meta
|
||||||
|
name="description"
|
||||||
|
content="Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты."
|
||||||
|
/>
|
||||||
|
<title>AI-разработка · Николай Мамадаев</title>
|
||||||
|
{{> head-links}}
|
||||||
|
{{> head-plyr}}
|
||||||
|
<style>
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
/* Сетка карточек проектов: 2 колонки, схлопывается в одну на мобильном */
|
||||||
|
.ai-projects {
|
||||||
|
list-style: none;
|
||||||
|
margin: 1.25rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
.ai-projects > li {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.ai-projects__media {
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
background: var(--surface);
|
||||||
|
}
|
||||||
|
.ai-projects__media img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
aspect-ratio: 16 / 10;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.ai-projects__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
.ai-projects__title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.05rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.ai-projects__stack {
|
||||||
|
margin: 0.3rem 0 0;
|
||||||
|
font-family: var(--font-mono, ui-monospace, monospace);
|
||||||
|
font-size: 0.78rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
.ai-projects__desc {
|
||||||
|
margin: 0.45rem 0 0;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: var(--text);
|
||||||
|
}
|
||||||
|
.ai-projects__links {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0.6rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.4rem 0.9rem;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
/* Навыки — компактные чипы переиспользуют стили тегов карточек активности */
|
||||||
|
.ai-stack-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 1rem 0 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.45rem;
|
||||||
|
}
|
||||||
|
.ai-stack-list li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.3rem 0.7rem;
|
||||||
|
border: 1px solid var(--line);
|
||||||
|
border-radius: 999px;
|
||||||
|
font-family: var(--font-mono, ui-monospace, monospace);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<p class="section__prose">
|
||||||
|
Больше десяти лет я проектировал интерфейсы. Теперь довожу идеи до работающего
|
||||||
|
кода: бэкенд, база данных, деплой. Инфраструктура тоже моя часть работы.
|
||||||
|
В большинстве проектов код пишет ИИ-агент. Я задаю архитектуру, проверяю
|
||||||
|
результат и отвечаю за то, что продукт вообще работает.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="roles">Что я делаю</h2>
|
||||||
|
<ul class="section__prose ai-stack-list">
|
||||||
|
<li>Продуктовая логика и API</li>
|
||||||
|
<li>Telegram-боты на aiogram 3</li>
|
||||||
|
<li>MCP-серверы</li>
|
||||||
|
<li>Плагины Figma и Obsidian</li>
|
||||||
|
<li>Автоматизация и агентные пайплайны</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="projects">Проекты</h2>
|
||||||
|
<ol class="ai-projects">
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Personal Assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM
|
||||||
|
в одном диалоге.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="{{casesPrefix}}ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Image Gen Bot</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Бот для генерации изображений: баланс, реферальная программа, админ-логи
|
||||||
|
в отдельные топики супергруппы.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="{{casesPrefix}}ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">MCP Image Server</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Собственный MCP-сервер для генерации картинок. Подключается к агентам
|
||||||
|
как инструмент.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/mcp-img-gen" target="_blank" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">AI assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Плагин для Figma, который исполняет скрипты прямо в редакторе.
|
||||||
|
ИИ-ассистент для любого тарифа.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="{{casesPrefix}}ai-assistant-figma/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Card Columns</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами
|
||||||
|
по тегам.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="{{casesPrefix}}card-columns-obsidian/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Hermes Desktop Plugins</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи
|
||||||
|
и контроль трат.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/unorouter-balance" target="_blank" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">Social Post Writer</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Бот, который превращает тезисы в готовый пост под нужную площадку и тон,
|
||||||
|
учитывая голос автора.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/social-post-writer-bot" rel="noopener noreferrer">Код</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<div class="ai-projects__media">
|
||||||
|
<img
|
||||||
|
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
|
||||||
|
alt=""
|
||||||
|
width="640"
|
||||||
|
height="400"
|
||||||
|
loading="lazy"
|
||||||
|
decoding="async"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="ai-projects__head">
|
||||||
|
<h3 class="ai-projects__title">AI Design Assistant</h3>
|
||||||
|
</div>
|
||||||
|
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
|
||||||
|
<p class="ai-projects__desc">
|
||||||
|
Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD.
|
||||||
|
Весь цикл создания вместе с ИИ-агентом.
|
||||||
|
</p>
|
||||||
|
<ul class="ai-projects__links">
|
||||||
|
<li><a href="{{casesPrefix}}site-portfolio/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2 id="stack">Стек</h2>
|
||||||
|
<ul class="section__prose ai-stack-list">
|
||||||
|
<li>Python</li>
|
||||||
|
<li>TypeScript</li>
|
||||||
|
<li>JavaScript</li>
|
||||||
|
<li>Go</li>
|
||||||
|
<li>HTML/CSS</li>
|
||||||
|
<li>GLSL</li>
|
||||||
|
<li>aiogram 3</li>
|
||||||
|
<li>FastAPI</li>
|
||||||
|
<li>PostgreSQL</li>
|
||||||
|
<li>Redis</li>
|
||||||
|
<li>SQLite</li>
|
||||||
|
<li>Docker</li>
|
||||||
|
<li>Coolify</li>
|
||||||
|
<li>Gitea</li>
|
||||||
|
<li>MCP</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="links">Где я это выкладываю</h2>
|
||||||
|
<p class="section__prose">
|
||||||
|
Код открыт: <a href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">GitHub</a>
|
||||||
|
и <a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin" target="_blank" rel="noopener noreferrer">Gitea</a>.
|
||||||
|
Сервисы, которые работают прямо сейчас, живут на
|
||||||
|
<a href="https://secrets-4-me.dynv6.net" target="_blank" rel="noopener noreferrer">secrets-4-me</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -18,6 +18,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ol id="mini-projects-list" class="mini-projects-grid" data-mini-projects-list>
|
<ol id="mini-projects-list" class="mini-projects-grid" data-mini-projects-list>
|
||||||
|
<li class="mini-projects-grid__item" data-mp-cells="2">
|
||||||
|
<a
|
||||||
|
class="mp-card mp-card--link mp-card--compact"
|
||||||
|
href="ai-dev/"
|
||||||
|
data-glass="false"
|
||||||
|
aria-label="AI-разработка — открыть страницу"
|
||||||
|
>
|
||||||
|
<div class="mp-card__body">
|
||||||
|
<h3 class="mp-card__title">AI-разработка</h3>
|
||||||
|
<ul class="mp-card__tags" aria-label="Тип проекта">
|
||||||
|
<li class="mp-card__tag">Боты · MCP · плагины</li>
|
||||||
|
</ul>
|
||||||
|
<p class="mp-card__desc">Не только дизайн, а целые продукты: от API до деплоя</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="mini-projects-grid__item" data-mp-cells="2">
|
<li class="mini-projects-grid__item" data-mp-cells="2">
|
||||||
<a
|
<a
|
||||||
class="mp-card mp-card--link mp-card--compact"
|
class="mp-card mp-card--link mp-card--compact"
|
||||||
|
|||||||
Reference in new issue
Block a user