SiteBrief: DevLab зсередини, як я обійшов Netlify і де AI облажався найбільше

💡 Усі статті, обговорення, новини про AI — в одному місці. Приєднуйтесь до AI спільноти!

(Перша частина — тут)

У першому пості я пообіцяв три речі: DevLab зсередини, Netlify ліміти і де AI помилявся найбільше. Сьогодні — все три.

DevLab зсередини

DevLab — це функція, яка дивиться на ваш репозиторій, знаходить проблеми і відкриває PR з готовим фіксом. Ви просто аппруваєте.

Як це влаштовано технічно:

  1. GitHub/GitLab шле webhook при кожному пуші в watched-гілку
  2. SiteBrief запускає повний скан: PageSpeed, security headers, SSL, SEO, bundle size
  3. Паралельно — читає файли репозиторію напряму через GitHub API: netlify.toml, .htaccess, nginx.conf, package.json, Dockerfile, .github/workflows/
  4. Якщо знайшов проблему і є готовий фікс — генерує новий вміст файлу, створює 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 + реальний браузер займає 30-50 секунд на сторінку.

Перша спроба: 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 з логотипом клієнта і клієнтський портал.

Питання, критика — в коментарях.

sitebrief.net

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Підписатись на коментарі