SiteBrief: DevLab зсередини, як я обійшов Netlify і де AI облажався найбільше
(Перша частина — тут)
У першому пості я пообіцяв три речі: DevLab зсередини, Netlify ліміти і де AI помилявся найбільше. Сьогодні — все три.
DevLab зсередини
DevLab — це функція, яка дивиться на ваш репозиторій, знаходить проблеми і відкриває PR з готовим фіксом. Ви просто аппруваєте.
Як це влаштовано технічно:
- GitHub/GitLab шле webhook при кожному пуші в watched-гілку
- SiteBrief запускає повний скан: PageSpeed, security headers, SSL, SEO, bundle size
- Паралельно — читає файли репозиторію напряму через GitHub API:
netlify.toml,.htaccess,nginx.conf,package.json,Dockerfile,.github/workflows/ - Якщо знайшов проблему і є готовий фікс — генерує новий вміст файлу, створює branch, комітить, відкриває PR
Не треба нічого встановлювати в репо. Webhook реєструється автоматично при підключенні.
Але є тонкість з гейтингом. Спочатку на Free плані я поставив ліміт: 5 PR на місяць. Здавалося розумним — поки не порахував: 20 сайтів на Free, один скан може одразу видати 10 issues. Ліміт вилітав за п’ять хвилин.
Переробив логіку. Тепер не кількість, а тип фіксу:
- Free: необмежено, але тільки базові — security headers, SEO, WordPress, CI/CD, npm залежності
- Pro+: ще й accessibility і PageSpeed фікси
Чому розмежування саме таке? Базові фікси генеруються локально без зовнішніх сервісів. Accessibility потребує реального браузера через Browserless — це платна інфраструктура. Тому логічно саме так.
Як я обійшов ліміти Netlify
Netlify вбиває синхронні функції через ~26 секунд. Для більшості задач це нормально. Але accessibility scan через axe-core + реальний браузер займає
Перша спроба: after() від Next.js — запустити важку роботу після відповіді клієнту. На локалі працює, на Netlify — ні. Netlify serverless просто не підтримує цей патерн належним чином.
Друга спроба: Netlify Background Functions — окремий тип функцій з лімітом 15 хвилин. Клієнт отримує 202 одразу, обробка йде у фоні. Саме те.
Схема:
POST /api/sites/:id/accessibility-scan → повертає 202 Accepted одразу → тригерить background function → background function запускає Browserless → результат пише в Supabase → клієнт поллить /api/sites/:id/accessibility-result
Але є ще одна проблема — axe-core і CSP. Якщо сайт має суворий Content-Security-Policy, він блокує інʼєкцію скриптів. Рішення: вбудовувати мінімізований axe-core прямо в page.evaluate() як рядок, а не підвантажувати зовні. Браузер виконує його в контексті сторінки, і CSP не блокує.
А окрема весела проблема — крон-джоби. Netlify native crons шлють заголовок x-netlify-event: schedule — без жодного Bearer токена. Моя авторизація перевіряла тільки Bearer. Результат: всі 25 крон-роутів мовчки повертали 401 два тижні, я нічого не помічав.
export function isCronAuthorized(request: Request): boolean {
const auth = request.headers.get('authorization')
if (auth === `Bearer ${process.env.CRON_SECRET}`) return true
if (request.headers.get('x-netlify-event') === 'schedule') return true
return false
}
Мораль: логуйте кожен запуск крону. Не тільки помилки — кожен. Інакше дізнаєтесь про проблему через місяць.
Де AI помилявся найбільше
Claude пише ~80% мого коду. Але є патерни помилок, які повторюються.
1. Впевнено вигадує API
Попросив реалізувати інтеграцію з однією платформою. Claude написав робочий, охайний код — з методами, які просто не існують в їхньому SDK. Жодного натяку на невпевненість. Код компілявся, але падав в рантаймі.
Правило: будь-яку зовнішню інтеграцію перевіряти по документації вручну, перш ніж довіряти коду.
2. Race conditions в async коді
AI пише async/await правильно в простих випадках. Але коли кілька операцій взаємодіють через shared state — регулярно отримую subtle race condition. Особливо в Supabase realtime + optimistic UI комбінаціях.
3. Не думає про edge cases на межах системи
«Що якщо webhook прийде двічі за 100мс?» — AI не питає. Я мав кілька дублікатів в базі через це. Зараз завжди явно прошу: «Подумай про ідемпотентність і race conditions.»
4. Занадто складні рішення для простих задач
Попросив «зробити пагінацію». Отримав абстракцію на 3 файли з generic типами. Для сторінки де 20 записів максимум. Треба явно казати: «Просте рішення, мінімум абстракцій.»
Наступний пост — про white-label: як влаштований кастомний домен для status page, PDF з логотипом клієнта і клієнтський портал.
Питання, критика — в коментарях.
Немає коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів