
OK3D
LiveПовноцінна платформа для вибору 3D-моделей і замовлення виробів з виготовленням та доставкою.
Full-Stack · Автоматизація · AI-системи · Інфраструктура
Сайти. Автоматизація. Боти. AI. Інфраструктура.
Якщо процес можна запрограмувати, з'єднати з іншими системами, автоматизувати чи посилити AI — я спроєктую і збудую систему навколо нього: від інтерфейсу й бекенду до сервера, на якому вона працює.
Що можна автоматизуватиОдна система, кожен шар — і вона працює сама.
Проєкти
Сайти, сервіси та системи, які я проєктую, розробляю й запускаю.

Повноцінна платформа для вибору 3D-моделей і замовлення виробів з виготовленням та доставкою.
Що я будую
Не одна сторінка й не один скрипт — робочий продукт: інтерфейс, бекенд, дані, автоматизація і сервер, на якому це все живе.
Фронтенд і бекенд як одне ціле — від лендінгу до маркетплейсу з адмінкою.
Усе, що працівник робить руками за розкладом, може робити скрипт — швидше й без помилок.
Боти, що приймають замовлення, повідомляють про події та дають команді адмінку прямо в месенджері.
Зібрати, очистити, зіставити й тримати в синхроні — тисячі сторінок, сотні тисяч рядків.
Локальні та хмарні моделі всередині продуктів: асистенти, агенти, генерація, пошук по власних даних.
Сервер, на якому живе продукт: Linux, Docker, reverse proxy, бекапи й моніторинг.
Процес
Той самий шлях і для лендінгу, і для системи з AI всередині. Різниця лише в глибині кожного кроку.
Частину кроків виконують AI-агенти під моїм контролем. Результат перевіряється в реальному браузері — скриншотом, а не на віру.
Автоматизація
Майже все, що повторюється. Ось як рутина, що з'їдає день працівника, перетворюється на систему, яка працює сама.
~2–4 години на день · помилки · затримки
за розкладом · 0 ручних кроків · усе в логах
Є задача, що повторюється? Автоматизуймо.
Описати задачуЯк це влаштовано
П'ять типових контурів, з яких складається більшість моїх проєктів. Кожен можна замовити окремо або як частину цілої системи.
«Парсер» — це не скрипт на одну сторінку. Це конвеєр: багато джерел, нормалізація, валідація, база — і споживачі, яким потрібні чисті дані.
Коли в сервісу немає API, з ним можна працювати через браузер — як людина, але за розкладом і з перевіркою результату.
Лише там, де це технічно й юридично доречно. Обхід захисних механізмів — не про це.
Не «просто бот», а вхід у систему: замовлення, сповіщення, адмінка та звіти — там, де команда вже сидить.
З'єдную системи, які не були створені для роботи разом: CRM, магазин, оплата, доставка, аналітика, Telegram, внутрішні бази.
Продукт живе на сервері, який я налаштовую і супроводжую сам: від reverse proxy до бекапів і GPU-навантажень.
Лабораторія
Невеликі інтерактивні демо. Кожне — спрощена версія того, що я будую насправді. Усе симулюється у вашому браузері й не під'єднано до живих систем.
URL → HTML → структуровані дані → JSON
// JSONБезпечне демо: парситься підготовлена сторінка, а не довільний сайт.
Один клік — відпрацьовує весь ланцюжок.
$ Чистий REST API — так я їх будую.
// responseЯк виглядає AI-шар усередині продукту: запитання → пошук по власних даних → відповідь.
Макет інтерфейсу — відповіді заскриптовані, дані не залишають сторінку.
Збірка → браузер → скриншот → аналіз → виправлення. Так перевіряється результат, а не приймається на віру.
$ Жива аналітика — та, що власник відкриває щоранку.
Типовий деплой — симуляція, безпечно.
Система
Наведіть або торкніться вузла, щоб побачити, що я можу зробити на цьому рівні.
Стек
Згруповано за шарами. Клацніть групу, щоб розгорнути.
Фронтенд
Бекенд
Дані
Автоматизація
AI
Інфраструктура
Інструменти
AI Lab
Локальні моделі на власному GPU-сервері — без оплати за токени й без витоку даних назовні. Таку ж схему можна розгорнути для вашого продукту.
Моделі
Не «підключив чат-бота», а окремий шар: модель, пошук по ваших даних та інструменти, що діють у вашій системі.
Генерація та обробка зображень і відео на власному GPU — воркфлоу ComfyUI, які можна вбудувати в конвеєр.
Статуси чесні: «робочий» — використовую в задачах, «експеримент» — працює, але ще не для продакшену, «дослідження» — вивчаю.
Не логотипи заради логотипів — що саме кожен інструмент робить у моїх системах.
Власна AI-платформа розробки
Я збираю локальне AI-асистоване середовище розробки: моделі, база знань, агенти з ролями, браузерна автоматизація та візуальна перевірка — на власній інфраструктурі.
Замість «згенерував код і повірив, що інтерфейс правильний» — середовище відкриває результат у браузері, дивиться на нього та ітерує.
Окремий шар знань про інтерфейси, щоб агент компонував сторінки не «як вийде», а за перевіреними патернами.
База — кураторські референси, документація, відкриті ресурси й метадані патернів. Не копії комерційних UI-бібліотек.
Код
Реалістичні фрагменти — інтеграція API, автоматизація, обробка даних. Без секретів і без hello-world.
<?php
declare(strict_types=1);
// Webhook нового заказа: подпись → валидация → БД → уведомление.
// Секреты берутся из окружения, в коде их нет.
$secret = getenv('ORDER_WEBHOOK_SECRET') ?: '';
$payload = file_get_contents('php://input');
$given = $_SERVER['HTTP_X_SIGNATURE'] ?? '';
if (!hash_equals(hash_hmac('sha256', $payload, $secret), $given)) {
http_response_code(401);
exit;
}
$order = json_decode($payload, true, 8, JSON_THROW_ON_ERROR);
$rules = [
'id' => fn($v) => is_int($v) && $v > 0,
'phone' => fn($v) => preg_match('/^\+?\d{10,15}$/', (string) $v),
'items' => fn($v) => is_array($v) && count($v) > 0,
'total' => fn($v) => is_numeric($v) && $v >= 0,
];
foreach ($rules as $field => $ok) {
if (!isset($order[$field]) || !$ok($order[$field])) {
http_response_code(422);
echo json_encode(['error' => "invalid {$field}"]);
exit;
}
}
$db = Db::connection();
$db->beginTransaction();
try {
$db->prepare(
'INSERT INTO orders (id, phone, total, status, created_at)
VALUES (:id, :phone, :total, "new", NOW())
ON DUPLICATE KEY UPDATE total = VALUES(total)'
)->execute([
'id' => $order['id'], 'phone' => $order['phone'], 'total' => $order['total'],
]);
$stmt = $db->prepare('INSERT INTO order_items (order_id, sku, qty) VALUES (?, ?, ?)');
foreach ($order['items'] as $item) {
$stmt->execute([$order['id'], $item['sku'], (int) $item['qty']]);
}
$db->commit();
} catch (Throwable $e) {
$db->rollBack();
error_log('order webhook: ' . $e->getMessage());
http_response_code(500);
exit;
}
// Уведомление — асинхронно, чтобы не держать вебхук открытым.
Queue::push('telegram.notify', [
'chat' => 'orders',
'text' => sprintf("🛒 Заказ #%d — %s ₴\n%d позиций",
$order['id'], number_format($order['total'], 0, '.', ' '), count($order['items'])),
]);
http_response_code(202);
echo json_encode(['ok' => true]);"""Мониторинг цен: обход по расписанию, история, AI-оценка изменений."""
from __future__ import annotations
import asyncio
import logging
from dataclasses import dataclass
from decimal import Decimal
import httpx
from tenacity import retry, stop_after_attempt, wait_exponential
from monitor.db import PriceRepo
from monitor.llm import classify_change
from monitor.notify import telegram
log = logging.getLogger(__name__)
@dataclass(frozen=True)
class Target:
sku: str
url: str
selector: str
@retry(stop=stop_after_attempt(4), wait=wait_exponential(min=2, max=30))
async def fetch_price(client: httpx.AsyncClient, target: Target) -> Decimal:
resp = await client.get(target.url, timeout=20)
resp.raise_for_status()
node = parse_html(resp.text).select_one(target.selector)
if node is None:
raise LookupError(f"selector miss: {target.sku}")
return normalize_price(node.get_text())
async def check(target: Target, repo: PriceRepo, client: httpx.AsyncClient) -> None:
price = await fetch_price(client, target)
previous = await repo.last(target.sku)
await repo.append(target.sku, price)
if previous is None or previous == price:
return
delta = (price - previous) / previous * 100
verdict = await classify_change(target.sku, previous, price, delta)
if verdict.significant:
await telegram.send(
"pricing",
f"📉 {target.sku}: {previous} → {price} ({delta:+.1f}%)\n{verdict.reason}",
)
async def main() -> None:
repo = PriceRepo.from_env()
targets = await repo.targets()
sem = asyncio.Semaphore(6) # не долбим один сайт параллельно
async with httpx.AsyncClient(headers={"User-Agent": "price-monitor/2.1"}) as client:
async def guarded(t: Target) -> None:
async with sem:
try:
await check(t, repo, client)
except Exception: # одна ошибка не должна ронять весь прогон
log.exception("target failed: %s", t.sku)
await asyncio.gather(*(guarded(t) for t in targets))
if __name__ == "__main__":
asyncio.run(main())// Тонкий API-клиент: дедупликация одинаковых запросов,
// отмена устаревших, оптимистичное обновление кэша.
const inflight = new Map();
export function createClient({ baseUrl, onError }) {
const cache = new Map();
async function request(method, path, { body, signal } = {}) {
const key = method === 'GET' ? `GET ${path}` : null;
if (key && inflight.has(key)) return inflight.get(key);
const run = fetch(baseUrl + path, {
method,
headers: { 'Content-Type': 'application/json' },
body: body ? JSON.stringify(body) : undefined,
signal,
})
.then(async (res) => {
if (!res.ok) throw new ApiError(res.status, await res.text());
return res.status === 204 ? null : res.json();
})
.catch((err) => {
if (err.name !== 'AbortError') onError?.(err);
throw err;
})
.finally(() => key && inflight.delete(key));
if (key) inflight.set(key, run);
return run;
}
return {
get: (path, opts) => request('GET', path, opts),
// Оптимистично: UI видит изменение сразу, откат — только при ошибке.
async patch(path, body, { optimistic } = {}) {
const prev = cache.get(path);
if (optimistic) cache.set(path, { ...prev, ...body });
try {
const data = await request('PATCH', path, { body });
cache.set(path, data);
return data;
} catch (err) {
cache.set(path, prev);
throw err;
}
},
// Поиск с отменой предыдущего запроса при новом вводе.
search: (() => {
let controller;
return (q) => {
controller?.abort();
controller = new AbortController();
return request('GET', `/search?q=${encodeURIComponent(q)}`, {
signal: controller.signal,
});
};
})(),
};
}
export class ApiError extends Error {
constructor(status, body) {
super(`API ${status}`);
this.status = status;
this.body = body;
}
}Досвід
10+ років
Кожен шар додавався, бо попереднього не вистачало, щоб випустити цілий продукт.
Сайти, верстка, CMS, перші бекенди на PHP.
API, бази даних, оплати, авторизація — логіка за інтерфейсом.
Парсери, боти, планувальники — прибираю ручну роботу з процесів.
Власні сервери: Linux, Docker, Nginx, бекапи, моніторинг.
Локальні моделі, агенти, RAG — AI як шар усередині продуктів.
Про мене
Я програмую понад 10 років. Працюю з усім стеком продукту — інтерфейс, бекенд, бази даних, автоматизація, сервери та AI.
Мені подобаються задачі, де софт може прибрати повторювану роботу або перетворити складний процес на просту систему.
Не автоматизуйте, бо це модно. Автоматизуйте, бо люди не повинні витрачати час на те, що софт робить надійніше.
Задачі, які я вирішую
Контакт
Розкажіть, що ви хочете автоматизувати, збудувати чи покращити. Не обов'язково знати, який стек потрібен — просто опишіть задачу.