<?xml version="1.0" encoding="utf-8" standalone="yes"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="uk">
  <title>Engineer — Software — Портфоліо та нотатки</title>
  <subtitle>Engineer ApS — розробка програмного забезпечення та IT-консалтинг у Копенгагені, Данія. Портфоліо підтверджених інженерних досягнень у даних, хмарі та IT.</subtitle>
  <id>https://software.engineer.company/uk/</id>
  <updated>2026-10-09T14:31:15+02:00</updated>
  <author>
    <name>Engineer ApS</name>
    <uri>https://software.engineer.company/uk/</uri>
    <email>welcome@engineer.company</email>
  </author>
  <rights>Авторське право © 2025 – дотепер · Engineer ApS</rights>
  <generator uri="https://gohugo.io/">Hugo 0.167.0</generator>
  <icon>https://software.engineer.company/assets/icons/apple/apple-touch-icon.png</icon>
  <logo>https://software.engineer.company/assets/images/brand/card.webp</logo>
  <link href="https://software.engineer.company/uk/" rel="alternate" type="text/html" />
  <link href="https://software.engineer.company/uk/atom.xml" rel="self" type="application/atom+xml" />
  <entry>
    <title>Спроєктувала комплексну інфраструктурну систему для науково‑дослідного інституту, що охопила 14 департаментів, з гнучкими модулями, уніфікованими пайплайнами даних та структурованими стратегіями підтримки для довгострокового впровадження.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-a-comprehensive-infrastructure-framework-for-a-research-institute-3/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-a-comprehensive-infrastructure-framework-for-a-research-institute-3/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Отриманий план інфраструктури виявився і технічно обґрунтованим, і стратегічно узгодженим із дослідницькими цілями інституту.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; У науково‑дослідному інституті, що об&amp;rsquo;єднував 14 різнопрофільних дослідницьких груп, кожна група працювала з різними джерелами даних, форматами, масштабами та програмними інструментами. Технічна експертиза та доступні ІТ‑ресурси суттєво відрізнялися між групами. Хоча декільком групам вдалося створити й розгорнути власні ІТ‑рішення, багато інших стикалися зі складністю власних потреб у сфері дата‑інфраструктури, що відволікало цінний час і увагу від основної дослідницької роботи.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб розробити рішення, яке дозволило б дослідникам зосередитися на науковій роботі, а не на ІТ‑проблемах. Метою було спроєктувати та впровадити масштабовану дата‑інфраструктуру для всього інституту, здатну задовольнити широкі та відмінні одна від одної вимоги більшості дослідницьких груп.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було розроблено надійний, перспективний план інфраструктури, що збалансовував гнучкість і стандартизацію. План окреслював ключові компоненти, такі як модульна архітектура, шляхи інтеграції різноманітних джерел даних, зручні для користувача інтерфейси, адаптовані до різного рівня технічних навичок, а також масштабовані рішення для зберігання та обробки даних. Він також охоплював стратегії впровадження, підтримки та управління, покликані забезпечити прийняття рішення й довгострокову стійкість.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Отриманий план інфраструктури виявився і технічно обґрунтованим, і стратегічно узгодженим із дослідницькими цілями інституту. Він об&amp;rsquo;єднав бачення управління даними в межах усієї організації, окреслив чіткий шлях до зменшення ІТ‑навантаження на дослідників і заклав основу для спільного, ефективного та готового до майбутнього дослідницького середовища даних. План отримав високу оцінку за інклюзивність, чіткість та адаптивність, задавши чіткий напрям трансформації дата‑інфраструктури інституту.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Прискорила продуктивність пайплайну географічних даних у 50 разів, вдосконаливши SQL‑програмування та моделювання даних у PostgreSQL, MS SQL та Google Cloud BigQuery.</title>
    <id>https://software.engineer.company/uk/portfolio/accelerated-geographical-data-pipeline-performance-by-50x-by-5/</id>
    <link href="https://software.engineer.company/uk/portfolio/accelerated-geographical-data-pipeline-performance-by-50x-by-5/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Сховища даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Оптимізація продуктивності баз даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування сховищ даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Ці комплексні оптимізації прискорили продуктивність пайплайну географічних даних у 50 разів, суттєво скоротивши час обробки даних.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Організація стикалася зі значними затримками в обробці великих обсягів географічних даних, що впливало на ефективність процесів прийняття рішень на основі даних та аналітичної звітності.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Мета полягала в тому, щоб оптимізувати пайплайн географічних даних для підвищення продуктивності та скорочення часу обробки, забезпечивши можливість ефективнішого проведення аналітики даних у режимі реального часу.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було ретельно проаналізовано наявні структури SQL‑програмування та моделювання даних у PostgreSQL, MS SQL і Google Cloud BigQuery, що виявило вузькі місця, пов&amp;rsquo;язані з неефективними стратегіями індексації, неоптимальним дизайном запитів та відсутністю належних обмежень. Для вирішення цих проблем:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Моделі даних було перепроєктовано для нормалізації критично важливих наборів даних, а також впроваджено стратегії партиціонування для скорочення часу отримання даних.&lt;/li&gt;&#xA;&lt;li&gt;Застосовано розширені техніки індексації, зокрема B‑tree та GiST індекси для PostgreSQL, фільтровані індекси в MS SQL і кластеризацію в BigQuery.&lt;/li&gt;&#xA;&lt;li&gt;Оптимізовано складні SQL‑запити шляхом рефакторингу підзапитів, скорочення операцій з&amp;rsquo;єднання та впровадження матеріалізованих подань там, де це доречно.&lt;/li&gt;&#xA;&lt;li&gt;Встановлено обмеження цілісності даних, такі як зовнішні ключі та обмеження перевірки, для забезпечення узгодженості даних без шкоди для продуктивності.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Ці комплексні оптимізації прискорили продуктивність пайплайну географічних даних у 50 разів, суттєво скоротивши час обробки даних. Це покращення уможливило аналітику в режимі реального часу, розширило можливості звітності та надало зацікавленим сторонам своєчасні дані для прийняття рішень, що зрештою сприяло ухваленню більш обґрунтованих стратегічних рішень.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Підвищила продуктивність застосунку географічних карт у 10 разів завдяки стратегічному переходу бази даних з MSSQL на PostgreSQL, включно з data cutover, оптимізувавши обробку та безпеку даних.</title>
    <id>https://software.engineer.company/uk/portfolio/improved-geographical-map-application-performance-by-10x-through-6/</id>
    <link href="https://software.engineer.company/uk/portfolio/improved-geographical-map-application-performance-by-10x-through-6/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Міграції та модернізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Міграція та модернізація баз даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Оптимізація продуктивності баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Досягнуто підвищення продуктивності просторових запитів у 10 разів, скоротивши середній час відповіді з 2,5 секунди до менш ніж 250 мілісекунд.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Географічний картографічний застосунок організації, що підтримував просторові запити в реальному часі для багатьох користувачів, зазнавав серйозних проблем із продуктивністю. Затримки при рендерингу картографічних шарів і виконанні запитів до даних на основі місцезнаходження впливали як на користувацький досвід, так і на надійність бекенд‑сервісів. Система працювала на застарілій базі даних Microsoft SQL Server (MSSQL), яка не мала нативної геопросторової індексації.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Підвищити продуктивність, масштабованість і безпеку картографічного застосунку, з конкретною метою скоротити затримку запитів і збільшити пропускну здатність для просторових операцій.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Здійснено стратегічну міграцію бази даних з MSSQL на PostgreSQL із розширенням PostGIS для забезпечення нативної підтримки геопросторових даних.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Спроєктовано нову схему, оптимізовану для просторових даних, з упровадженням індексів GIST та SP‑GiST на стовпцях geometry та geography для пришвидшення запитів.&lt;/li&gt;&#xA;&lt;li&gt;Визначено суворі обмеження зовнішніх ключів і обмеження перевірки для забезпечення реляційної цілісності та застосування правил валідації даних для просторових координат.&lt;/li&gt;&#xA;&lt;li&gt;Мігровано понад 50 мільйонів просторових записів за допомогою ETL‑пайплайнів із кроками трансформації даних для відповідності новим стандартам SRID (EPSG:4326).&lt;/li&gt;&#xA;&lt;li&gt;Налаштовано параметри конфігурації PostgreSQL (наприклад, work_mem, effective_cache_size) для оптимальної продуктивності вводу‑виводу за умов паралельного доступу.&lt;/li&gt;&#xA;&lt;li&gt;Впроваджено рольове керування доступом (RBAC) та безпеку на рівні рядків для забезпечення політик захисту даних для кількох груп користувачів.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Досягнуто підвищення продуктивності просторових запитів у 10 разів, скоротивши середній час відповіді з 2,5 секунди до менш ніж 250 мілісекунд. Навантаження на CPU бекенду знизилося на 65%, а доступність системи покращилася в періоди пікового навантаження. Рівень безпеки також посилено завдяки деталізованим політикам доступу та обмеженням валідації даних, що зменшило ймовірність пошкодження просторових даних.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Вирішила 1 000 проблем у географічних даних та часових рядах, використовуючи GDAL, ArcGIS, PostGIS, Mapbox, QGIS, SQL (PL/pgSQL, Transact‑SQL), Bash, забезпечивши високоякісну обробку великих даних.</title>
    <id>https://software.engineer.company/uk/portfolio/resolved-1-000-issues-in-geographical-data-and-7/</id>
    <link href="https://software.engineer.company/uk/portfolio/resolved-1-000-issues-in-geographical-data-and-7/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Завдяки цим зусиллям було усунено понад 1 000 критичних проблем, що суттєво покращило точність даних і швидкість обробки.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Під час роботи над масштабним проєктом геопросторової аналітики команда виявила численні невідповідності й аномалії в географічних наборах даних і часових рядах. Ці проблеми впливали на точність просторового аналізу та інструментів прийняття рішень, що використовувалися в кількох підрозділах.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Відповідальність полягала в тому, щоб виявити, усунути та оптимізувати понад 1 000 проблем якості даних у цих складних наборах даних для забезпечення цілісності та продуктивності подальших застосунків і візуалізацій.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Просторові помилки систематично діагностувалися та виправлялися за допомогою комбінації інструментів, зокрема GDAL, QGIS та ArcGIS, а автоматизовані робочі процеси на Bash дозволяли пришвидшити повторювані завдання з очищення даних. PostGIS забезпечував виконання складних просторових запитів і просторову індексацію, а надійні процедури на PL/pgSQL і Transact‑SQL використовувалися для управління та трансформації географічних і часових даних у базах даних PostgreSQL та SQL Server. Крім того, очищені дані було інтегровано в інтерактивні візуалізації за допомогою Mapbox, що підвищило доступність даних для кінцевих користувачів.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Завдяки цим зусиллям було усунено понад 1 000 критичних проблем, що суттєво покращило точність даних і швидкість обробки. Це безпосередньо сприяло скороченню часу виконання просторових запитів на 35% і уможливило проведення командою надійнішого просторового аналізу. Робота забезпечила постійну доступність якісних, готових до використання даних для аналітики та звітності, підтримуючи стратегічні рішення в межах усієї організації.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала, реалізувала та адмініструвала 6 пайплайнів ETL/ELT, використовуючи Google BigQuery, MSSQL, PostgreSQL, Shell scripting, PL/pgSQL та Transact‑SQL, інтегрувавши дані для ефективної обробки через Python API.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-implemented-and-administered-6-etl-elt-pipelines-8/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-implemented-and-administered-6-etl-elt-pipelines-8/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Cloud" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Мережі та VPN" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Сховища даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування сховищ даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Ці автоматизовані пайплайни суттєво скоротили ручні витрати та час обробки — з понад 3 годин ручної роботи до менш ніж 20 хвилин наскрізно, водночас покращивши…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Організації потрібно було консолідувати та обробляти великі обсяги структурованих даних із віддаленого сховища даних, розташованого за IPSec VPN. Ці дані мали критичне значення для роботи внутрішніх аналітичних дашбордів і зовнішніх Python API, якими користувалися клієнти й партнери.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Мета полягала в тому, щоб спроєктувати, реалізувати та підтримувати набір надійних автоматизованих ETL/ELT‑пайплайнів для безпечного отримання, трансформації та завантаження даних у Google BigQuery, забезпечуючи точність даних, продуктивність і масштабованість у всіх системах.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було спроєктовано, реалізовано та адміністровано 6 наскрізних ETL/ELT‑пайплайнів на основі кількох технологій, включно з Google BigQuery, MSSQL, PostgreSQL, Shell‑скриптами, PL/pgSQL та Transact‑SQL.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Налагоджено захищені з&amp;rsquo;єднання з віддаленим сервером, захищеним IPSec VPN, для автоматизації отримання даних.&lt;/li&gt;&#xA;&lt;li&gt;Заплановано та виконано завантаження стиснутих архівів даних, що містили файли Parquet, CSV та .bak.&lt;/li&gt;&#xA;&lt;li&gt;Розроблено скрипти на Bash і Python для витягування та класифікації файлів за типом і схемою.&lt;/li&gt;&#xA;&lt;li&gt;Для файлів .bak резервні копії відновлювалися в локальному екземплярі MSSQL Server за допомогою робочих процесів RESTORE DATABASE, а цілісність схеми перевірялася.&lt;/li&gt;&#xA;&lt;li&gt;Завантажено структуровані дані в проміжні схеми в MSSQL і PostgreSQL за допомогою інструментів bcp, psql та SSIS, залежно від формату джерела.&lt;/li&gt;&#xA;&lt;li&gt;Написано модульні та придатні для повторного використання процедури PL/pgSQL і T‑SQL для очищення, нормалізації та збагачення даних відповідно до бізнес‑логіки.&lt;/li&gt;&#xA;&lt;li&gt;Експортовано впорядковані набори даних і таблиці в проміжні формати, стиснуто їх за допомогою gzip і безпечно передано в бакет Google Cloud Storage.&lt;/li&gt;&#xA;&lt;li&gt;Автоматизовано процеси завантаження та зіставлення схем у Google BigQuery за допомогою bq CLI та скриптів для завантаження даних на основі Python.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Ці автоматизовані пайплайни суттєво скоротили ручні витрати та час обробки — з понад 3 годин ручної роботи до менш ніж 20 хвилин наскрізно, водночас покращивши актуальність даних із щотижневої до щоденної синхронізації. Python API, що споживали ці дані, отримали приріст продуктивності на 30%, а покращена прозорість допомогла бізнес‑аналітикам швидше надавати інсайти зацікавленим сторонам. Рішення залишається масштабованим і легко розширюваним для підключення нових джерел даних у міру зростання бізнесу.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Реалізувала 8 проєктів Power BI з докладними посібниками, інтегрувавши інструменти Microsoft Power BI з NodeJS API та Python FastAPI для ефективної аналітики та візуалізації даних.</title>
    <id>https://software.engineer.company/uk/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/</id>
    <link href="https://software.engineer.company/uk/portfolio/delivered-8-power-bi-projects-with-comprehensive-manuals-10/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Аналітика даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Аналітика даних та BI‑дашборди" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Успішно реалізовано 8 проєктів з аналітики даних, підвищивши ефективність формування звітів на 60% і давши змогу міжфункціональним командам ухвалювати швидші…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Організації потрібні були динамічні візуальні уявлення про складні набори даних, що охоплювали продуктивність електромереж і показники географічного розподілу, для підтримки прийняття рішень у технічних і стратегічних командах.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Розробити інтерактивні дашборди та рішення для звітності, здатні ефективно подавати як дані в реальному часі, так і історичні географічні та електричні дані, даючи змогу зацікавленим сторонам швидко виявляти тренди, аномалії та показники продуктивності.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Інтегровано Microsoft Power BI з власним бекенд‑стеком на основі NodeJS API та Python FastAPI для оптимізації приймання, трансформації та візуалізації даних. Спроєктовано й реалізовано дашборди з картографічними візуалізаціями, показниками споживання енергії, відстеженням відключень та індикаторами ефективності електромережі. Розроблено багаторазові шаблони та детальну документацію для підтримки масштабованості та зручності використання.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Успішно реалізовано 8 проєктів з аналітики даних, підвищивши ефективність формування звітів на 60% і давши змогу міжфункціональним командам ухвалювати швидші рішення на основі даних. Зацікавлені сторони повідомили про суттєве покращення розуміння регіональної продуктивності електромереж і точності планування ресурсів.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Випустила 500 звітів з аналізу даних електроенергетики та GIS, застосовуючи поглиблені дослідження та усунення несправностей для забезпечення точної аналітики географічних і часових великих даних.</title>
    <id>https://software.engineer.company/uk/portfolio/released-500-electricity-and-gis-data-analysis-reports-11/</id>
    <link href="https://software.engineer.company/uk/portfolio/released-500-electricity-and-gis-data-analysis-reports-11/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Аналітика даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Сховища даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Аналітика даних та BI‑дашборди" scheme="https://software.engineer.company/uk/services/" />
    <summary>Звіти стали стандартним довідковим матеріалом у різних підрозділах, допомагаючи в балансуванні регіонального навантаження, плануванні енергоефективності та…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Команда управляла величезними наборами даних, що генерувалися розумними лічильниками, встановленими в кількох географічних регіонах. Ці розумні лічильники виробляли деталізовані часові ряди даних про споживання електроенергії, які використовували енергетичні аналітики, інженери та регіональні планувальники для операційних і стратегічних рішень.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Відповідальність полягала в тому, щоб готувати якісні, прозорі та відтворювані аналітичні звіти, здатні виявляти патерни у споживанні енергії, виявляти аномалії та визначати регіональні тренди використання, водночас гарантуючи, що нетехнічні зацікавлені сторони зможуть легко інтерпретувати й повторно використовувати результати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було створено та надано понад 500 детальних аналітичних звітів, використовуючи чистий SQL для виконання всіх завдань з видобування, трансформації та аналізу даних, працюючи безпосередньо в хмарних середовищах, таких як PostgreSQL і BigQuery. Дані включали геолокаційні координати, ідентифікатори лічильників, дані про споживання енергії з часовими мітками та метадані про довкілля. SQL‑скрипти використовували CTE, віконні функції, підзапити та геопросторові з&amp;rsquo;єднання, що забезпечувало масштабовану та ефективну обробку.&lt;/p&gt;&#xA;&lt;p&gt;Кожен звіт містив анотований SQL‑код, що давало змогу колегам і співавторам повністю відтворити й перевірити дослідження, що суттєво скорочувало час, необхідний для подальшого аналізу. Також додавалися нотатки з усунення несправностей і документувалися типові проблеми якості даних, такі як відсутні GPS‑координати або пошкоджені значення лічильників, разом із рекомендованими процедурами їх обробки.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Звіти стали стандартним довідковим матеріалом у різних підрозділах, допомагаючи в балансуванні регіонального навантаження, плануванні енергоефективності та виявленні аномалій. Забезпечуючи повну прозорість і відтворюваність, ця робота допомогла підвищити довіру зацікавлених сторін до даних і сприяла створенню точніших прогнозних моделей та покращенню ефективності операційного планування на 10–15%.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала, створила та керувала 100 базами даних сховищ даних на PostgreSQL, MS SQL та Google BigQuery, переважно з GIS‑даними та часовими рядами, оптимізувавши продуктивність і масштабованість.</title>
    <id>https://software.engineer.company/uk/portfolio/architected-created-and-managed-100-postgresql-ms-sql-12/</id>
    <link href="https://software.engineer.company/uk/portfolio/architected-created-and-managed-100-postgresql-ms-sql-12/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Сховища даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Адміністрування баз даних (DBA)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Оптимізація продуктивності баз даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування сховищ даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Ці ініціативи призвели до суттєвих покращень: - Приріст продуктивності: час відповіді на запити для GIS-даних і часових рядів скоротився на 40–60%, що…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; У технологічній компанії, що стрімко зростала, виникла критична потреба створювати, керувати та оптимізувати різноманітний портфель зі 100+ баз даних у PostgreSQL, Microsoft SQL Server та Google BigQuery. Ці бази даних переважно оброблювали складні набори даних, включно з даними геоінформаційних систем (GIS) (наприклад, просторові координати та аналітика на основі місцезнаходження) і часовими рядами (наприклад, показання сенсорів, логи та метрики в реальному часі). Наявна інфраструктура стикалася з проблемами масштабованості, продуктивності запитів і узгодженості даних, особливо в міру експоненційного зростання обсягу даних. Організації була потрібна надійна архітектура для забезпечення надійності даних і скорочення операційних витрат.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Основна мета полягала в тому, щоб спроєктувати, реалізувати та підтримувати масштабовану, високопродуктивну екосистему сховища даних, адаптовану для GIS‑даних і часових рядів. Це включало:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Усунення вузьких місць продуктивності в складних просторових і часових запитах.&lt;/li&gt;&#xA;&lt;li&gt;Забезпечення масштабованості для обробки зростаючих обсягів даних при збереженні економічної ефективності.&lt;/li&gt;&#xA;&lt;li&gt;Співпрацю з міжфункціональними командами (наприклад, дата‑сайєнтистами, продукт‑менеджерами) для узгодження дизайну бази даних з бізнес‑потребами.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Для досягнення цих цілей:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Спроєктовано масштабовані архітектури:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Створено нормалізовані та денормалізовані схеми для PostgreSQL і SQL Server із застосуванням просторової індексації (наприклад, PostGIS для PostgreSQL) і партиціонування часових рядів для оптимізації продуктивності запитів.&lt;/li&gt;&#xA;&lt;li&gt;Використано таблиці BigQuery з розбиттям за часом та кластеризацією для ефективної обробки великомасштабних часових рядів.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;2&#34;&gt;&#xA;&lt;li&gt;Впроваджено стратегії оптимізації:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Застосовано техніки оптимізації запитів, такі як індексація, матеріалізовані подання та кешування, для скорочення затримки GIS‑запитів і запитів до часових рядів.&lt;/li&gt;&#xA;&lt;li&gt;Застосовано стиснення даних і колонкове зберігання в BigQuery для мінімізації витрат на зберігання й підвищення швидкості сканування.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;Здійснено співпрацю щодо міжплатформної інтеграції:&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Задокументовано найкращі практики моделювання GIS‑даних і часових рядів для орієнтування команд у майбутніх проєктах.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Ці ініціативи призвели до суттєвих покращень:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Приріст продуктивності: час відповіді на запити для GIS‑даних і часових рядів скоротився на 40–60%, що уможливило швидшу аналітику та прийняття рішень.&lt;/li&gt;&#xA;&lt;li&gt;Операційна надійність: автоматизований моніторинг скоротив час простою на 50%, тоді як стандартизовані процеси підвищили продуктивність команди та зменшили кількість помилок.&lt;/li&gt;&#xA;&lt;li&gt;Вплив на бізнес: оптимізована інфраструктура дала змогу компанії запустити нові продукти на основі даних (наприклад, дашборди аналітики в реальному часі) і виконати нормативні вимоги щодо управління даними (data governance).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Ця робота зміцнила здатність організації розв&amp;rsquo;язувати складні проблеми, пов&amp;rsquo;язані з даними.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Автоматизувала розгортання GIS SaaS‑застосунку, обробку даних та систему звітності за допомогою GitHub Actions CI/CD, Python, Bash та SQL.</title>
    <id>https://software.engineer.company/uk/portfolio/automated-gis-saas-application-deployment-data-processing-and-16/</id>
    <link href="https://software.engineer.company/uk/portfolio/automated-gis-saas-application-deployment-data-processing-and-16/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Cloud" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Розгортання, обробка даних та звітність стали автоматизованими й надійними, ручна рутина зникла з плеча команди, а цикл релізів скоротився.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Розгортання GIS SaaS‑застосунку, обробка його даних та формування звітів були повністю ручними кроками — а ручні кроки одночасно й повільні, і тихо небезпечні. Кожен реліз забирав час інженерів і ніс ризик помилки, а повторювана робота з даними та звітністю сиділа там, з&amp;rsquo;їдаючи потужність тиждень за тижнем.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завданням була автоматизація всього шляху від коду до продакшну, а також повторюваної обробки даних і звітності — з метою отримати релізи, які були б швидкими, безпечними та відтворюваними, а не ретельним ручним ритуалом щоразу.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Весь шлях було автоматизовано. Пайплайни GitHub Actions взяли на себе цикл test‑build‑deploy, тож реліз перестав залежати від того, чи хтось пам&amp;rsquo;ятає всі кроки. Повторювана обробка даних та звіти перейшли в заплановані завдання на Python, Bash та SQL, тож вони просто виконувалися, а не були чиєюсь рутинною роботою. А конфігурація та секрети були стандартизовані так, щоб кожне середовище поводилося однаково — саме це усуває несподіванки на кшталт «у мене на машині працює», бо не залишається «моєї машини», яка відрізняється від продакшну.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Розгортання, обробка даних та звітність стали автоматизованими й надійними, ручна рутина зникла з плеча команди, а цикл релізів скоротився. Команда змогла зосередити увагу на продукті, а не на операціях, що його оточували.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Автоматизувала постачання 20 пайплайнів GIS‑даних та ETL‑процесів даних застосунку, оптимізувавши автоматизацію інфраструктури та звітність.</title>
    <id>https://software.engineer.company/uk/portfolio/automated-delivery-of-20-gis-data-pipelines-and-17/</id>
    <link href="https://software.engineer.company/uk/portfolio/automated-delivery-of-20-gis-data-pipelines-and-17/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Моніторинг та observability" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Усі двадцять пайплайнів та їхній ETL працювали автоматично й передбачувано, а вся картина автоматизації інфраструктури та звітності стала охайнішою.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа працювала на великій кількості GIS‑пайплайнів даних та ETL‑процесів для даних застосунку, які постачалися й контролювалися вручну. Ручні пайплайни створюють вузькі місця, вони втрачають узгодженість, і найгірше — вони несуть постійний невеликий ризик того, що один із них тихо відмовить, і ніхто цього не помітить, доки дані далі за потоком уже не стануть неправильними.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завданням була автоматизація постачання цих пайплайнів та ETL‑процесів — щоб дані надходили надійно та передбачувано без того, щоб хтось їх супроводжував.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Двадцять GIS‑пайплайнів даних та ETL для даних застосунку перейшли на автоматизоване постачання, від початку до кінця. Планування, логування та обробку відмов було стандартизовано, тож кожен пайплайн поводився однаково і, що важливо, було видно, коли якийсь із них поводився інакше — тиха відмова залишається тихою, лише якщо ніхто не стежить. І їх було вбудовано в наявну автоматизацію інфраструктури та звітність, тож вони стали частиною однієї узгодженої системи, а не шухляди зі скриптами, які хтось мусив пам&amp;rsquo;ятати запустити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Усі двадцять пайплайнів та їхній ETL працювали автоматично й передбачувано, а вся картина автоматизації інфраструктури та звітності стала охайнішою. Бізнес отримав надійні, актуальні дані без того, щоб хтось проводив їх вручну — і без ризику тихої відмови, що висів над цим.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Очолила розробку програмного забезпечення GIS‑картографічного застосунку, збільшивши дохід у 10 разів та позиціонувавши продукт як основний актив даних.</title>
    <id>https://software.engineer.company/uk/portfolio/led-the-software-development-of-a-gis-map-24/</id>
    <link href="https://software.engineer.company/uk/portfolio/led-the-software-development-of-a-gis-map-24/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Керівництво командою" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Менторство та коучинг" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>GIS-застосунок став наріжним каменем SaaS-платформи, забезпечивши зростання доходу у 10 разів завдяки допродажам, ліцензуванню даних та залученню нових…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Основним викликом була побудова платформи, здатної відстежувати, моніторити та оптимізувати активи відновлюваної енергетики, такі як сонячні панелі та вітрові турбіни. Проте початкове рішення не мало надійних геопросторових можливостей, через що клієнтам було важко візуалізувати розташування активів, аналізувати просторові дані чи отримувати практичні висновки. Розпізнавши цю прогалину, керівна команда пріоритизувала розробку GIS‑застосунку (Geographic Information System) для карт, щоб підвищити цінність платформи та відповідати потребам клієнтів, що змінювалися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завданням було очолити розробку GIS‑застосунку — критичного компонента для диференціації продукту на конкурентному ринку зеленої енергетики. Роль виходила за межі розробки програмного забезпечення, охоплюючи технічного лідера, DevOps‑інженера, інженера даних та SRE (Site Reliability Engineer), забезпечуючи узгодженість рішення з траєкторією зростання компанії. Метою було створити масштабований, інтуїтивно зрозумілий GIS‑інструмент, що безшовно інтегрувався б із SaaS‑платформою, даючи змогу користувачам візуалізувати розташування активів, відстежувати показники продуктивності та використовувати просторові дані для прийняття рішень. Це вимагало балансування технічних інновацій з обмеженнями зростаючого стартапу, забезпечуючи водночас можливість продукту розвиватися разом із компанією.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Почалося зі співпраці із зацікавленими сторонами для визначення основних функцій GIS‑застосунку, з фокусом на інтеграцію з наявною SaaS‑платформою та візуалізацію даних у реальному часі. З огляду на невеликий розмір команди, було спроєктовано модульну архітектуру з використанням бібліотек GIS з відкритим кодом, щоб система залишалася легкою й масштабованою. Також були впроваджені пайплайни CI/CD, автоматизоване надання інфраструктурних ресурсів та інструменти моніторингу для забезпечення надійності. У міру зростання команди нових інженерів наставляли, налагоджували міжфункціональну співпрацю та пріоритизували зворотний зв&amp;rsquo;язок від користувачів для ітеративного вдосконалення застосунку. З часом GIS‑інструмент еволюціонував від базового прототипу до складної платформи, включаючи розширену аналітику та кастомні дашборди для задоволення потреб клієнтів.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; GIS‑застосунок став наріжним каменем SaaS‑платформи, забезпечивши зростання доходу у 10 разів завдяки допродажам, ліцензуванню даних та залученню нових клієнтів. Його здатність візуалізувати активи зеленої енергетики в реальному часі підвищила операційну ефективність для клієнтів, а безперервне вдосконалення інструменту закріпило за ним статус основного інформаційного активу. Успіх проєкту не лише зміцнив репутацію компанії в секторі відновлюваної енергетики, а й продемонстрував цінність міждисциплінарного підходу в динамічному стартап‑середовищі. Поєднання технічної експертизи зі стратегічним баченням зробило GIS‑застосунок ключовим диференціатором, що підживлював довгострокове зростання та інновації.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Керувала full‑stack розробкою GIS‑карт, наглядаючи за PostgreSQL, Mapbox, ReactJS та NodeJS, щоб постачити інтегроване рішення.</title>
    <id>https://software.engineer.company/uk/portfolio/directed-full-stack-gis-map-development-overseeing-postgresql-25/</id>
    <link href="https://software.engineer.company/uk/portfolio/directed-full-stack-gis-map-development-overseeing-postgresql-25/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>У результаті вийшов єдиний інтегрований картографічний застосунок, у якому дані, рендеринг та інтерфейс нарешті тягнули в один бік.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; На цьому етапі GIS‑карта перестала бути просто функцією і стала причиною, чому клієнти взагалі заходили в систему. Проблема полягала в тому, що вона розросталася фрагментарно. Просторові дані зберігалися в PostgreSQL, саму карту малював Mapbox, а застосунок навколо неї складався з ReactJS на фронтенді та NodeJS на бекенді. Кожна частина працювала сама по собі. Просто їх не було побудовано так, щоб вони поєднувалися одна з одною, і шви вже почали розходитися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Роль охоплювала full‑stack розробку карти та відповідний технічний напрям: модель даних, рендеринг, API та React‑фронтенд. Метою було перетворити чотири речі, які випадково опинилися в одному репозиторії, на єдиний продукт, за який не соромно.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Спочатку було визначено архітектуру, а далі робота велася близько до коду, а не з відстані. З боку даних просторову модель у PostgreSQL підтримували в порядку, щоб запити не сповільнювалися до повзання зі зростанням наборів даних. Mapbox відповідав за малювання; завдання полягало в тому, щоб подавати йому правильні дані на правильних рівнях масштабування, а не все одразу. З боку застосунку код на ReactJS і NodeJS проходив перевірку, команду підштовхували до спільних конвенцій, а відповідальність постійно повертали на той рівень, якому вона належала, щойно вона починала протікати в сусідній. Значна частина цієї роботи була неефектною: виловлювати дрібні неузгодженості, доки вони не застигли в архітектурі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; У результаті вийшов єдиний інтегрований картографічний застосунок, у якому дані, рендеринг та інтерфейс нарешті тягнули в один бік. Він став ключовою частиною платформи — тим, що команда могла й далі розширювати, не побоюючись, що все ламатиметься щоразу, коли додається новий шар.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Оптимізувала стратегії прогнозування та інвестування для 11 операторів електромереж, підвищивши операційну ефективність за допомогою GIS‑рішень на основі даних.</title>
    <id>https://software.engineer.company/uk/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/</id>
    <link href="https://software.engineer.company/uk/portfolio/optimized-forecasting-and-investment-strategies-for-11-electricity-27/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Аналітика даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Аналітика даних та BI‑дашборди" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>Оператори отримали прогнози, яким можна довіряти, та інвестиційні рішення, спрямовані на конкретну мету, а не засновані на сподіваннях.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Оператори електромереж живуть і гинуть рішеннями про те, де підсилювати мережу і куди вкладати гроші, а одинадцять із них ухвалювали ці рішення майже без геопросторового аналізу під ними. У них були операційні дані. Чого в них не було — це способу побачити ці дані на карті, там, де насправді живуть закономірності.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб за допомогою GIS загострити їхнє прогнозування та інвестиційні стратегії — перетворити таблиці показників на щось, що показувало б, де потужність стає обмеженою, де накопичується ризик і куди найдоцільніше спрямувати наступні кошти.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Їхні операційні дані було об&amp;rsquo;єднано з геопросторовим моделюванням так, щоб вони підсилювали одне одного. Замість абстрактного прогнозування мережу можна було розглядати просторово й ставити конкретні запитання: які ділянки наближаються до своїх меж, які території виправдовують інвестиції в першу чергу. Для одинадцяти операторів це означало підганяти аналіз під те, як кожен із них фактично керує своєю мережею, а не пропонувати всім один шаблон у надії, що він підійде.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Оператори отримали прогнози, яким можна довіряти, та інвестиційні рішення, спрямовані на конкретну мету, а не засновані на сподіваннях. Прив&amp;rsquo;язка планування до того, що показувала карта, зробила весь процес ефективнішим — гроші та увага спрямовувалися туди, куди вказували дані, а не туди, куди вела звичка.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Представила 200 покращень UI/UX для GIS‑картографічного застосунку, збільшивши дохід у 10 разів завдяки вдосконаленим функціям програмного забезпечення.</title>
    <id>https://software.engineer.company/uk/portfolio/presented-200-ui-ux-improvements-for-the-gis-28/</id>
    <link href="https://software.engineer.company/uk/portfolio/presented-200-ui-ux-improvements-for-the-gis-28/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Аналітика даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>Інтерфейс став помітно зручнішим у використанні, а цінність продукту зросла відповідно: ця робота сприяла зростанню доходу у 10 разів.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Інтерфейс карти став потужним і водночас — ускладненим. Були місця, де було відчутно, що клієнти не отримують цінність, яка лежала прямо перед ними, — хороша функціональність, замкнена за незграбними взаємодіями. Цей розрив між тим, що продукт умів робити, і тим, що людям було легко робити, непомітно коштував бізнесу грошей.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб знайти ці розриви і провести виправлення до кінця: роботу з юзабіліті, яка мала зробити продукт простішим для отримання цінності і, не випадково, комерційно ціннішим.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Замість того, щоб здогадуватися, що не так, робота велася на основі зворотного зв&amp;rsquo;язку та даних про використання, і з цього утворився беклог із 200 конкретних покращень UI/UX. До них не ставилися як до рівнозначних — їх ранжували за впливом, а ті, що мали значення, відстоювалися і проводилися через команду, щоб бути випущеними як реальні функції, а не як список побажань, що застарівав у документі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Інтерфейс став помітно зручнішим у використанні, а цінність продукту зросла відповідно: ця робота сприяла зростанню доходу у 10 разів. Це приклад, вартий того, щоб до нього повертатися, бо він чітко доводить думку — ретельна робота над UX не є косметикою, вона позначається на рахунку.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Керувала виконанням 30 успішних GIS‑проєктів, продемонструвавши керівництво в постачанні інноваційних рішень у галузі.</title>
    <id>https://software.engineer.company/uk/portfolio/managed-the-execution-of-30-successful-gis-projects-32/</id>
    <link href="https://software.engineer.company/uk/portfolio/managed-the-execution-of-30-successful-gis-projects-32/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Agile та Scrum" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Керівництво командою" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Управління проєктами" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Управління проєктами (Agile)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Формування команди та менторство" scheme="https://software.engineer.company/uk/services/" />
    <summary>Усі тридцять проєктів було здано. Ця послідовність важила більше, ніж будь-який окремий проєкт, — клієнт, який тридцять разів бачив постачання вчасно, не…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Компанія заробляла на постачанні GIS‑проєктів, і водночас їх виконувалося багато. Зростання компанії трималося на тому, щоб надійно доводити їх до завершення, — не один флагманський проєкт, зроблений блискуче, а стабільний потік проєктів, що здавалися вчасно й трималися купи, а це можливо лише тоді, коли координація в команді дійсно працює.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Відповідальність полягала в тому, щоб забезпечити постачання цього портфеля — тримати обсяг, людей і терміни узгодженими по всьому портфелю та давати команді напрямок для випуску.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; За ці роки через цю роль пройшло постачання тридцяти GIS‑проєктів. На практиці це означало утримувати обсяг стабільним, коли він намагався розповзатися, спрямовувати потрібних людей на потрібну роботу і триматися достатньо близько до кожного проєкту, щоб ловити проблеми, поки вони ще були малими. Якщо щось мало зірвати терміни, краще було дізнатися про це рано й перегрупуватися, ніж дізнатися про це на дедлайні. Значна частина роботи полягала просто в тому, щоб утримувати всі тарілки в повітрі та чесно інформувати клієнта про те, що і коли буде готове.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Усі тридцять проєктів було здано. Ця послідовність важила більше, ніж будь‑який окремий проєкт, — клієнт, який тридцять разів бачив постачання вчасно, не хвилюється за тридцять перший, і ця репутація значною мірою пояснює, чому компанія продовжувала зростати.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Очолила розробку, розгортання та підтримку понад 30 GIS‑проєктів, продемонструвавши експертизу в технологіях PostgreSQL, Bash, Python, JavaScript, GDAL, ArcGIS, PostGIS та Mapbox.</title>
    <id>https://software.engineer.company/uk/portfolio/led-the-development-deployment-and-support-of-over-35/</id>
    <link href="https://software.engineer.company/uk/portfolio/led-the-development-deployment-and-support-of-over-35/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Керівництво командою" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Понад тридцять проєктів було побудовано, розгорнуто і підтримувано в усьому цьому діапазоні. Відповідальність за весь життєвий цикл, а не лише за побудову, —…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Увесь випуск компанії становив GIS «на замовлення» — кастомна картографія та просторові системи, побудовані під конкретну проблему клієнта, а потім підтримувані в роботі після запуску. Побудувати систему — це лише половина справи; геопросторовий проєкт, який запускається, а потім падає в продакшені, насправді не було доставлено.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Ці проєкти проходили через цю роль від початку до кінця — розробка, розгортання та підтримка після запуску — з технічним керівництвом у доволі широкому стеку технологій.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Постачання охопило понад тридцять GIS‑проєктів, з практичною роботою по всьому стеку. PostgreSQL із PostGIS в основі для просторових даних, GDAL/OGR для перенесення їх між форматами — shapefiles, GeoJSON, GeoTIFF, KML, vector tiles — а також QGIS і JOSM для самої роботи з даними. На фронті — вебкарти, побудовані на Mapbox GL і Leaflet, іноді з використанням API ArcGIS чи HERE, з рівнем застосунку на JavaScript, Python, PHP і SQL. Робота охоплювала діапазон від 2D- і 3D‑цифрової картографії через обробку LiDAR, георектифікацію та векторизацію до карт приміщень і навігації в них. І відповідальність не закінчувалася на моменті запуску — розгортання та подальша підтримка в продакшені теж входили до неї, тож проблеми не передавалися комусь іншому; з ухваленими рішеннями доводилося жити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Понад тридцять проєктів було побудовано, розгорнуто і підтримувано в усьому цьому діапазоні. Відповідальність за весь життєвий цикл, а не лише за побудову, — саме те, що тримало якість чесною: проєктування відбувається інакше, коли знаєш, що саме тобі дзвонитимуть, якщо щось зламається.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Долучилася до процесів проєктування користувацьких інтерфейсів, забезпечивши інтуїтивні, візуально привабливі та зручні для користувача інтерфейси проєктів.</title>
    <id>https://software.engineer.company/uk/portfolio/contributed-to-user-interface-design-processes-ensuring-intuitive-36/</id>
    <link href="https://software.engineer.company/uk/portfolio/contributed-to-user-interface-design-processes-ensuring-intuitive-36/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <summary>Інтерфейси стали інтуїтивнішими та відшліфованішими, що кінцеві користувачі відчували безпосередньо, і це підняло загальну якість того, що випускалося.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Інтерфейси в проєктах компанії були нерівномірними за якістю. Деякі були непогані, деякі явно були побудовані інженерами, які думали про модель даних, а не про людину, якій доведеться цим користуватися, і рішення щодо дизайну не завжди ухвалювалися з думкою про кінцевого користувача. Особливо на вебкартографічному продукті карта — це найпростіша частина; саме в елементах керування, фільтрації та потоці навколо неї люди губляться.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Участь у процесі UI‑дизайну була частиною ролі — допомагати робити інтерфейси такими, що люди справді вважали б їх інтуїтивними та приємними у використанні, а не просто функціональними.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Роль не була роллю дизайнера, але вона була присутня в процесі дизайну і привносила інженерну перспективу — акцентуючи увагу на розкладці, на потоці проходження завдання, на тому, чи справді екран був зрозумілим, чи лише звичним для тих, хто його побудував. Це були фронтенди на React, Angular і Vue поверх карт Mapbox і Leaflet, і значна частина юзабіліті полягала в деталях: як фільтрувався набір даних, як відбувався перехід між поверхами на карті приміщення, чи повідомляла система, що саме вона робить. Здебільшого це означало ставити «наївні» запитання від імені користувача рано, поки їх було ще дешево виправити, а не після релізу, коли плутанина поверталася у вигляді звернень у підтримку.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Інтерфейси стали інтуїтивнішими та відшліфованішими, що кінцеві користувачі відчували безпосередньо, і це підняло загальну якість того, що випускалося. Те, що питання юзабіліті ставилися під час дизайну, а не після релізу, — це здебільшого і є те, що визначило різницю.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Реорганізувала внутрішні процеси, заощадивши 8 000 годин завдяки вдосконаленню архітектури програмного забезпечення, систем та ефективності планування.</title>
    <id>https://software.engineer.company/uk/portfolio/overhauled-internal-processes-saving-8-000-hours-by-38/</id>
    <link href="https://software.engineer.company/uk/portfolio/overhauled-internal-processes-saving-8-000-hours-by-38/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Управління проєктами" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <category term="Управління проєктами (Agile)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Переробка зекономила приблизно 8 000 годин завдяки суттєвому підвищенню ефективності архітектури, систем і планування.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; У внутрішніх процесах накопичилися типові нашарування — архітектура програмного забезпечення, що розросталася стихійно, а не за задумом, системи, які працювали, але неефективно, і планування, через яке люди то простоювали, то були перевантажені. Нічого з цього не «горіло», саме тому це й залишали без змін, але тихо це коштувало багато часу.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Метою було докорінно переглянути ці процеси — знайти витрати й усунути їх, а не продовжувати за них платити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Внутрішні процеси було перероблено за трьома напрямами: архітектуру програмного забезпечення — так, щоб її можна було логічно осмислювати й розвивати, а не обходити; системи — оптимізовано так, щоб рутинна робота більше не займала більше часу, ніж потрібно; і планування — так, щоб потужності справді відповідали обсягу роботи. Зміни закріпили так, щоб вони прижилися, — вбудували в те, як працює команда, а не залишили у вигляді меморандуму, який усі кивнули й забули, — адже покращення процесів, які не закріплюються, просто відкочуються назад до старого способу роботи.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Переробка зекономила приблизно 8 000 годин завдяки суттєвому підвищенню ефективності архітектури, систем і планування. Це потужності, які пішли безпосередньо на роботу з вищою цінністю, а не на накладні витрати, які раніше ніхто навіть не ставив під сумнів.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Розробила систему звітності Data Analytics, збільшивши квартальний дохід від програмного забезпечення на 400% завдяки PDF‑звітам на базі Python.</title>
    <id>https://software.engineer.company/uk/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/</id>
    <link href="https://software.engineer.company/uk/portfolio/developed-a-data-analytics-reporting-system-increasing-quarterly-44/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Аналітика даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Стейкхолдери та звітність" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Аналітика даних та BI‑дашборди" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>Саме ця звітність спричинила зростання квартального доходу від програмного забезпечення на 400%. Покращення й пришвидшення аналітики не було просто зручністю…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Зацікавлені сторони не отримували аналітику у своєчасній, зрозумілій формі. Дані існували, але перетворення їх на щось, на основі чого справді можна ухвалювати рішення, відбувалося повільно й вручну, тож видимість того, як усе працює, відставала, а разом із нею відставали й комерційні рішення.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завданням було побудувати систему звітності з аналізу даних — таку, що перетворювала б необроблені дані на чіткі, регулярні висновки без ручного складання щоразу.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Систему звітності, яка генерувала PDF‑звіти на Python, було побудовано так, щоб автоматизувати весь ланцюжок: вибірку даних, проведення аналізу та представлення результатів у чіткому, узгодженому форматі, який зацікавлені сторони справді могли прочитати. Суть полягала в регулярності та ясності — той самий професійний звіт з&amp;rsquo;являвся передбачувано, тож цифри стали тим, на що люди дивилися як на звичну справу, а не тим, що доводилося самостійно розшукувати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Саме ця звітність спричинила зростання квартального доходу від програмного забезпечення на 400%. Покращення й пришвидшення аналітики не було просто зручністю для бек‑офісу — коли перед людьми, які ухвалюють комерційні рішення, з&amp;rsquo;являються чіткі й своєчасні цифри, рішення стають кращими, і тут це напряму позначилося на доході.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Розробила 100 вебзастосунків за допомогою HTML/HTML5, CSS/SCSS, Django, WordPress та Joomla, забезпечивши різноманітну онлайн‑присутність.</title>
    <id>https://software.engineer.company/uk/portfolio/developed-100-web-applications-using-html-html5-css-51/</id>
    <link href="https://software.engineer.company/uk/portfolio/developed-100-web-applications-using-html-html5-css-51/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сто застосунків дали клієнтам різноманітну, дієву присутність онлайн, кожен реалізований на технології, яка справді йому підходила.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Клієнти хотіли вебзастосунки, і хотіли вони дуже різні речі — різні масштаби, різні бюджети, різні рівні від «просто виведіть мене онлайн» до «зробіть мені щось індивідуальне». Відповідати цьому означало бути універсальним, а не заганяти кожного клієнта в межі однієї й тієї самої технології.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб створювати вебзастосунки, які давали б кожному клієнту різноманітну й ефективну присутність онлайн.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було створено сто вебзастосунків, і суть полягала в тому, щоб підбирати інструмент під завдання, а не мати улюблений. Там, де клієнту потрібне було щось індивідуальне, у хід ішли HTML/HTML5, CSS/SCSS та Django; там, де потрібне було щось більш стандартне, з чим клієнт міг би впоратися і самостійно, швидшою й розумнішою відповіддю ставали WordPress або Joomla. Частина майстерності полягала саме в тому, щоб розрізняти ці випадки — відмовити клієнту в індивідуальній розробці, яка йому не потрібна, або переконати в тій, яка потрібна.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сто застосунків дали клієнтам різноманітну, дієву присутність онлайн, кожен реалізований на технології, яка справді йому підходила. Саме підбір підходу під клієнта, а не навпаки, зробив їх ефективними, а не просто зданими в експлуатацію.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала 30 вебсайтів, надавши унікальні та гнучкі рішення завдяки перетворенню дизайнів Photoshop на HTML.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-30-websites-delivering-unique-and-flexible-solutions-52/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-30-websites-delivering-unique-and-flexible-solutions-52/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Тридцять сайтів відповідали своїм дизайнам і залишалися придатними до роботи — самобутні, вишукані вебсайти, які не ламалися від першого ж редагування…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Клієнти приходили з бажаним виглядом сайту — часто це вже був готовий візуальний дизайн — і потребували, щоб вебсайт був побудований точно за ним. Розрив між файлом дизайну та робочим сайтом — це саме те місце, де здебільшого виграється або втрачається якість: легко здати щось приблизно правильне, але з непомітними відхиленнями.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб проєктувати сайти й перетворювати дизайни на точні, гнучкі реалізації.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Спроєктовано тридцять вебсайтів, і дизайни з Photoshop вручну перетворено на HTML. Точність була стандартом — відступи, типографіка, деталі, які насправді мав на увазі дизайнер, а не їх наближення — але так само важливою була і гнучкість, адже сайт, який збігається з макетом піксель у піксель, а потім розвалюється щойно змінюється контент, насправді побудовано погано. Тож мета полягала в розмітці, яка залишалася вірною дизайну і водночас лишалася придатною до подальшої підтримки.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Тридцять сайтів відповідали своїм дизайнам і залишалися придатними до роботи — самобутні, вишукані вебсайти, які не ламалися від першого ж редагування контенту. Вірність дизайну при збереженні придатності до підтримки — саме той баланс, що мав значення, і саме до нього прийшли ці сайти.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Адмініструвала 40 вебсайтів на хостинг‑серверах Ubuntu Linux з Apache та Nginx, забезпечивши високу доступність і продуктивність.</title>
    <id>https://software.engineer.company/uk/portfolio/administered-40-websites-on-ubuntu-linux-hosting-servers-53/</id>
    <link href="https://software.engineer.company/uk/portfolio/administered-40-websites-on-ubuntu-linux-hosting-servers-53/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Linux та сервери" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <summary>Усі сорок сайтів працювали з високою доступністю та гарною продуктивністю, що дало клієнтам хостинг, про який не треба було думати.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Існував портфель робочих вебсайтів, які мали залишатися онлайн і швидкими — а хостинг це ще одна з тих робіт, які непомітні, доки сайт не впаде, і от тоді про нього думають усі й нічого більше.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб адмініструвати ці сайти та підтримувати їхню високу доступність і швидкість.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Сорок вебсайтів працювали на хостинг‑серверах Ubuntu Linux, на поєднанні Apache та Nginx — конфігурація, налаштування продуктивності, постійне обслуговування для підтримання надійності під реальним трафіком. Саме реальний трафік тут ключовий: сайт, який нормально почувається, коли ним ніхто не користується, і падає, щойно ним починають користуватися, насправді не адмініструвався — його просто залишили без уваги. Тож робота полягала в тому, щоб підтримувати їхню справність під фактичним навантаженням.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Усі сорок сайтів працювали з високою доступністю та гарною продуктивністю, що дало клієнтам хостинг, про який не треба було думати. Стабільність і надійність під реальним використанням — це вся суть хостингу, і саме це забезпечили ці сайти.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала, розробила, впровадила та підтримувала інфраструктуру, обробку даних і картографічний застосунок безперервно протягом 2 років без вихідних, свят чи відпустки, по 10–14 годин на день.</title>
    <id>https://software.engineer.company/uk/portfolio/architected-developed-implemented-supported-infrastructure-data-processing-and-55/</id>
    <link href="https://software.engineer.company/uk/portfolio/architected-developed-implemented-supported-infrastructure-data-processing-and-55/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="GIS / геопростір" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="GIS та геопросторові рішення" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Платформа залишалася безперервно доступною та еволюціонувала від крихкого раннього прототипу до надійного хребта продукту, підтримуючи компанію протягом…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Стартап у сфері зеленої енергетики на ранній стадії розвитку залежав від єдиної платформи для відстеження, моніторингу та оптимізації активів відновлюваної енергетики, проте не мав ані окремої інфраструктурної команди, ані сформованої інженерної організації для її побудови й експлуатації. Усю технічну основу — хмарну інфраструктуру, пайплайни обробки даних і клієнтський GIS‑застосунок з картою — потрібно було створити й підтримувати в безперервній роботі на ринку, де будь‑який простій чи розрив у даних напряму підривав довіру клієнтів і дохід.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб одноосібно спроєктувати, побудувати та експлуатувати всю систему наскрізно, охоплюючи інженерію платформи й даних, DevOps та забезпечення надійності (site reliability). Окрім написання коду, це означало відповідальність за продакшн: розгортання та убезпечення інфраструктури, проєктування рівня обробки даних, що живив карту, і гарантування безперервної доступності застосунку для зростаючої бази клієнтів — і все це в межах обмежень і невпинного темпу стартапу, що стрімко розвивався.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Протягом двох років інфраструктура, пайплайни даних і картографічний застосунок проєктувалися, впроваджувалися та підтримувалися без перерв — без вихідних, свят чи відпусток, часто по 10–14 годин на день. Було обрано прагматичну, модульну архітектуру, щоб зберегти придатність до підтримки одноосібної експлуатації, з автоматизованим розгортанням, моніторингом та сповіщеннями, аби проблеми виявлялися й вирішувалися швидко. Обробка даних постійно донастроювалася для надійності та продуктивності, релізи випускалися поступово, і кожен рівень — від серверів до карти, орієнтованої на користувача, — підтримувався та вдосконалювався особисто, у відповідь на реальне використання клієнтами.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Платформа залишалася безперервно доступною та еволюціонувала від крихкого раннього прототипу до надійного хребта продукту, підтримуючи компанію протягом критичної фази зростання завдяки одноосібній відповідальності одного інженера. Таке безпосереднє, практичне управління забезпечувало достатню надійність інфраструктури, даних і картографічного застосунку для підтримки допродажів, ліцензування даних і залучення нових клієнтів, а також продемонструвало рідкісний рівень відданості, широти охоплення й наскрізної відповідальності на всіх рівнях стеку.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Оптимізувала бюджетні витрати у 10 разів без втрати продуктивності для міжнародного клієнта, переосмисливши загальну інфраструктуру, усунувши непотрібні сервіси та перенісши систему з хмари AWS.</title>
    <id>https://software.engineer.company/uk/portfolio/optimized-budget-costs-10-times-with-zero-loss-56/</id>
    <link href="https://software.engineer.company/uk/portfolio/optimized-budget-costs-10-times-with-zero-loss-56/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Cloud" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Міграції та модернізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Хмарна інфраструктура та міграція" scheme="https://software.engineer.company/uk/services/" />
    <summary>Бюджетні витрати скоротилися приблизно у 10 разів, без жодної втрати продуктивності — та сама спроможність за частку тієї суми, яку сплачували раніше.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Міжнародний клієнт ніс на собі суттєво роздуті інфраструктурні витрати. Її налаштування AWS було надлишково забезпечене ресурсами й накопичило сервіси, якими вже ніхто не користувався, тож рахунок за хмару повністю вийшов з будь‑якої пропорції до того, що бізнесу дійсно було потрібно. Історія звична — ніхто не планує перевитрачати, це просто накопичується, коли ніхто не стежить за лічильником.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб суттєво скоротити витрати без жодної втрати продуктивності, а це означало по‑справжньому переосмислити інфраструктуру, а не підрізати по краях — підрізання по краях рідко відчутно змінює рахунок, який структурно є занадто великим.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Тож робота велася наскрізно. Спочатку проведено аудит того, що фактично використовувалося — саме тут проявляють себе дубльовані та непотрібні сервіси — і їх було прибрано. Потім усе, що залишилося, приведено у відповідність до реального попиту замість розрахунків на найгірший сценарій, закладених у початкове налаштування. А головним кроком стало повне перенесення навантажень з AWS на більш економічно вигідний варіант хостингу — виконане обережно, поетапно, так, щоб діючий бізнес жодного разу не відчув, як під ним відбувається міграція.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Бюджетні витрати скоротилися приблизно у 10 разів, без жодної втрати продуктивності — та сама спроможність за частку тієї суми, яку сплачували раніше. Це вивільнило реальну суму коштів, яка місяць за місяцем тихо витікала у надто великий рахунок за хмару, а для бізнесу це означало гроші, що напряму повернулися до чистого прибутку.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала багаторівневу морську платформу, розділивши фронтенд Next.js PWA, API на Go (Huma/Fiber) та рівень функцій PostgreSQL, зберігши всю бізнес‑логіку в базі даних.</title>
    <id>https://software.engineer.company/uk/portfolio/architected-a-layered-maritime-platform-separating-a-next-57/</id>
    <link href="https://software.engineer.company/uk/portfolio/architected-a-layered-maritime-platform-separating-a-next-57/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Систему й далі було легко тримати в голові. Бізнес-логіка розташована в одному місці, яке справді можна перевірити, API — нудний у хорошому сенсі адаптер, а…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Продукт мав стати морською платформою — професійні мережі, відгуки про компанії, спонсорована освіта — і це був молодий продукт, що є ввічливим способом сказати, що вимоги мали суттєво змінюватися. Чого варто було уникнути — це архітектури, у якій зміна бізнес‑правила означала одночасне втручання у фронтенд, API та базу даних. На невеликій кодовій базі, яка швидко росте, саме такий рівень зв&amp;rsquo;язаності перетворює зміну у два рядки коду на роботу на ціле пообіддя.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Як архітектору, першим рішенням, яке треба було ухвалити, було те, де мала жити кожна логіка, з межами, достатньо чіткими, щоб витримувати тиск, а не розмиватися, щойно хтось поспішав.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Усе усталилося у три рівні, кожен зі своєю роллю. Фронтенд на Next.js відповідає за представлення й інтерактивність і більше ні за що. API на Go — Huma поверх Fiber — навмисно тонкий: він маршрутизує, валідує запит, застосовує фільтрацію безпеки та оркеструє, але не містить жодної бізнес‑логіки. Уся бізнес‑логіка живе у функціях PostgreSQL, які збирають повний результат і повертають його, щоб API просто передав далі. Тож коли правило змінюється, воно змінюється в одному рівні, у SQL, а решта двох про це навіть не знають. Межі було зафіксовано письмово, а потім закріплено через код‑рев&amp;rsquo;ю, адже конвенція, яку ніхто не контролює, перестає бути конвенцією.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Систему й далі було легко тримати в голові. Бізнес‑логіка розташована в одному місці, яке справді можна перевірити, API — нудний у хорошому сенсі адаптер, а фронтенд не переймається, коли схема змінюється під ним. Саме це розділення дало продукту змогу й далі нарощувати функціональність без тихого гниття архітектури.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала архітектуру наскрізної передачі JSON, у якій функції PostgreSQL повертають повний JSON, що дослівно пересилається через Go API, усунувши проміжний unmarshalling та унезалежнивши фронтенд від змін схеми.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-a-json-passthrough-architecture-where-postgresql-functions-58/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-a-json-passthrough-architecture-where-postgresql-functions-58/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Код обробників став суттєво коротшим, а що важливіше — фронтенд перестав бути прив&#39;язаним до Go. Достатньо змінити те, що повертає функція, і нова форма даних…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Звичний шлях даних від бази до браузера — це естафета трансформацій. База даних передає API рядки, API десеріалізує їх у структури (structs), переформатовує, серіалізує назад у JSON, і лише тоді дані йдуть далі. Кожен із цих переходів — це код, який потрібно написати, код, який потрібно протестувати, і ще одне місце, де уявлення API про дані та уявлення бази даних про них можуть розійтися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Ідея полягала в тому, щоб прибрати цю естафету. Якщо база даних могла б повертати готову відповідь, API міг би просто передавати її далі, а фронтенд міг би залежати безпосередньо від форми даних бази даних замість її вручну підтримуваної копії, що живе в Go.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Тож це було побудовано як пряму передачу без проміжних перетворень. Функції PostgreSQL збирають усю відповідь у вигляді JSON — формування є завданням SQL, виконуваним там, де дані вже є. Обробник на Go отримує це назад як json.RawMessage і передає далі без змін; він ніколи не розкладає це на частини, ніколи не перекодовує. Невеликий допоміжний метод QueryJSON перетворив цей патерн на шлях найменшого опору, а не на те, про що щоразу треба пам&amp;rsquo;ятати окремо. Випало все проміжне обладнання, яке зазвичай накопичує традиційний шаруватий API — DTO, мапери, структури відповідей.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Код обробників став суттєво коротшим, а що важливіше — фронтенд перестав бути прив&amp;rsquo;язаним до Go. Достатньо змінити те, що повертає функція, і нова форма даних напряму доходить до клієнта без редагування жодного рядка коду обробника. Менше рухомих частин, і цілий клас розбіжностей між рівнями тут просто не існує.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала систему перемикання контексту організації з клієнтським localStorage та серверним дзеркалюванням cookie, що дозволила користувачам діяти від імені керованих організацій, забезпечуючи авторизацію за принципом найменших привілеїв.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-an-organization-context-switching-system-with-client-59/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-an-organization-context-switching-system-with-client-59/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <summary>Користувач може діяти від імені будь-якої організації, якою керує, без жодних перешкод, а інтерфейс залишається синхронізованим і на клієнті, і на сервері.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; На платформі морський фахівець може керувати організаціями — компаніями, академіями — які не мають власних облікових записів для входу. Обліковим записом є сама людина; організація — це те, від імені чого вона діє. Тож користувачу потрібно переміщуватися по всьому застосунку як будь‑яка з організацій, якими він керує, вільно перемикаючись між ними, і ця зручність не повинна перетворюватися на діру в авторизації.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Перемикання контексту мало бути швидким і непомітним для користувача, і водночас потрібно було гарантувати, що активний контекст сам собою ніколи не надасть доступу, на який немає прав.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; За це відповідає OrganizationContext зі зберіганням стану на обох сторонах. На клієнті джерелом істини щодо того, від імені якої організації користувач наразі діє, є localStorage, тож перемикання відбувається миттєво — без звернення до сервера. Серверний cookie дзеркалить цей стан, щоб сторінки, що рендеряться на сервері, визначали той самий контекст під час SSR; на сервері є getServerViewMode, який його зчитує. Важливо, що жодне з цього не використовується для ухвалення рішень щодо доступу. Авторизація повторно перевіряється на сервері під час кожного запиту. Контекст на фронтенді існує заради досвіду користування — показати саме те, що потрібно, — а сервер є єдиним джерелом істини щодо того, що дозволено робити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Користувач може діяти від імені будь‑якої організації, якою керує, без жодних перешкод, а інтерфейс залишається синхронізованим і на клієнті, і на сервері. Але оскільки права щоразу перевіряються на сервері, ця зручність жодним чином не послаблює безпеку. Втручання у вміст localStorage змінює лише те, що бачить власний інтерфейс користувача, і нічого більше — сервер усе одно відмовить.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Мігрувала HTTP API з Fiber на Huma v2 — 649 шляхів і 760 операцій — досягнувши та втримавши 100% відповідність між маршрутами, які реєструє сервер, і описом OpenAPI, який він публікує.</title>
    <id>https://software.engineer.company/uk/portfolio/migrated-the-http-api-from-fiber-to-huma-60/</id>
    <link href="https://software.engineer.company/uk/portfolio/migrated-the-http-api-from-fiber-to-huma-60/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Міграції та модернізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Нові ендпоінти отримують валідацію та актуальну документацію без додаткових зусиль, а цілий клас помилок обробки запитів — на кшталт «ой, а тут ми забули…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; API розпочинав своє життя на Fiber, із валідацією запитів, написаною вручну для кожного ендпоінта окремо. Це нормально, коли ендпоінтів жменька. Але перестає бути нормальним, коли поверхня API розростається: рукописна валідація перетворюється на податок на підтримку, а дрібні неузгодженості накопичуються, бо перевірки кожного ендпоінта — це своя окрема сніжинка. І ніде не було жодного єдиного опису форми API.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Метою було отримати валідацію, що походить із типів, а не з рукописних перевірок, і справжній контракт, який описує API, — без зупинки на повномасштабне переписування.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; HTTP‑рівень перенесено на Huma v2 поверх Fiber, тож наявний рантайм зберігся. Кожен ендпоінт отримує вхідні та вихідні структури (structs), а Huma генерує валідацію запитів і моделювання відповіді на основі цих типів. Опис OpenAPI виходить із цього безкоштовно, а це означає, що документація йде в ногу з кодом, а не застаріває десь у вікі. Усе нове писалося під Huma, а наявні маршрути перенесено, залишивши рівно два ендпоінти на чистому Fiber — це WebSocket‑ендпоінти, де справді потрібен саме сокет, а модель запиту/відповіді Huma не підходить. Те, у що це виросло, — 649 шляхів із 760 операціями та перевірка в CI, яка порівнює маршрути, що їх сервер справді реєструє, з тими, що їх декларує опис OpenAPI. Паритет становить 100%, і він там і лишається, бо маршрут, який не описано, завалює білд.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Нові ендпоінти отримують валідацію та актуальну документацію без додаткових зусиль, а цілий клас помилок обробки запитів — на кшталт «ой, а тут ми забули перевірити це поле» — зник. На 760 операціях цей опис — єдиний практичний спосіб, у який хтось узагалі читає API, тож гарантія його повноти важить більше, ніж важила на п&amp;rsquo;ятдесяти. Типізований контракт зробив API одночасно безпечнішим для змін і простішим для передачі іншій людині, адже типи самі повідомляють, чого очікує ендпоінт.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Згенерувала контракт API з бази даних назовні — OpenAPI, типізований TypeScript‑клієнт на 44 076 рядків, 61 mock‑обробник та обмеження, які застосовує UI, — з перевіркою на кожній ланці, що падає при розходженні.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-request-schema-validation-contract-with-automated-61/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-request-schema-validation-contract-with-automated-61/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <summary>Поле не може змінитися лише з одного боку — воно завалюється на першому ж переході, який це помічає, у білді, за кілька хвилин після зміни.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Фронтенд і бекенд розвиваються у власному темпі, і їхні уявлення про payload запиту можуть непомітно розходитися. Зазвичай про це дізнаються за 422 у браузері — вже після того, як розбіжність потрапила в продакшн, а це найдорожчий момент, щоб про неї дізнатися. Написання обох сторін вручну за одним документом цього не виправляє: воно лише переносить розбіжність на того, хто забув перечитати документ.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Обидві сторони мали генеруватися з одного джерела, а не узгоджуватися між двома, і кожен крок цієї генерації мав перевірятися, а не братися на віру.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Ланцюг починається з бази даних і йде назовні. Схема та її функції визначають структури даних; типи Go визначають API; Huma формує з них опис OpenAPI; з цього опису генерується типізований клієнт TypeScript — 44 076 рядків; поряд із ним генерується 61 mock‑обробник, тож власні тести фронтенду виконуються проти реального контракту, а не проти рукописної фікстури; а обмеження, які UI застосовує до форми, походять із того самого місця, замість того щоб їх перенабирали у валідаторі. Кожен перехід має запобіжник. Перевірка контракту в CI порівнює те, що надсилає фронтенд, із тим, що очікує API, і завалює білд за розбіжності, а під нею є перевірка схеми, яка звіряє реальну структуру даних, а не її опис. Вона свідомо охоплює місця, де розбіжності люблять ховатися: опціональні поля тіла запиту, де плутають «відсутнє» і null, та enum‑и query‑параметрів, де обидві сторони можуть тихо розійтися в допустимих значеннях.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Поле не може змінитися лише з одного боку — воно завалюється на першому ж переході, який це помічає, у білді, за кілька хвилин після зміни. Це усунуло повторюваний і по‑справжньому набридливий клас багів: непомітний під час code review і такий, що проявляється лише в рантаймі. Ціна — крок генерації посеред усього: перегенерація є рутиною, а ланцюг вартий довіри рівно настільки, наскільки надійна його найменш захищена ланка, — тому запобіжник отримав кожен перехід.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала електронну пошту як можливість платформи — три провайдери з резервним перемиканням, webhooks доставки, логування надсилання й доставки, шаблонізацію та кампанії — за перевіркою під час запуску, яка не дасть застосунку стартувати без жодного з них.</title>
    <id>https://software.engineer.company/uk/portfolio/built-email-as-a-platform-capability-with-failover-62/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-email-as-a-platform-capability-with-failover-62/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Cloud" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Ціла категорія тихих збоїв перейшла зі стану «користувач помічає це через кілька днів» у стан «розгортання зупиняється», а невдалий день у провайдера став…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Електронна пошта відіграє значну роль на платформі — верифікація, сповіщення, дайджести, кампанії, усе те, на що користувач насправді чекає. А поштовий провайдер — це саме той тип залежності, що тихо ламається: конфігурація виглядає нормально, застосунок запускається, і про проблему дізнаються лише тоді, коли реальна людина так і не отримує обіцяного листа. Це найгірший спосіб про це дізнатися. З одним провайдером усе ще гірше, бо збій є повним, а виправляти його — комусь іншому.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Пошту потрібно було трактувати як спроможність, якою володіє платформа, а не як клієнтську бібліотеку, яку вона викликає, — здатну пережити збій провайдера, здатну сказати, що сталося з конкретним листом, і голосну під час запуску в тих середовищах, де мовчання небезпечне.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Три провайдери стоять за одним інтерфейсом — SendGrid як основний, а SMTP2GO та Azure Communication Services позаду нього, — і перемикання між ними автоматичне, а не є зміною конфігурації, зробленою під тиском. Доставка не вважається даністю: вхідні webhooks повідомляють, що кожен провайдер зробив із листом, і обидві сторони записуються — у журнал надсилань і таблицю подій доставки, — тож «чи отримала ця людина свій лист із верифікацією» є запитом, а не здогадом. Шаблонізація тримає тіла листів поза кодом, а окрема схема broadcast — 5 таблиць і 24 функції — доставляє кампанії сегментам користувачів, і це інша задача, ніж транзакційна пошта, тож її й будували як іншу. Перед усім цим стартова перевірка надсилає реальний лист через увесь стек, за прапорцем: у середовищі розробки це просто логує попередження й продовжує роботу, бо ніхто не хоче, щоб ноутбук відмовлявся запускатися через прострочений ключ пісочниці, а в staging і production збій є фатальним і процес завершується, а не розгортає білд, який не може надсилати пошту. Сам шлях надсилання проходить через клієнт із захистом від SSRF і тайм‑аутом 30 секунд, а асинхронний шлях доставки має retries і backoff, тож короткочасний збій не втрачає повідомлення.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Ціла категорія тихих збоїв перейшла зі стану «користувач помічає це через кілька днів» у стан «розгортання зупиняється», а невдалий день у провайдера став деградованим шляхом, а не аварією. Ціна — три інтеграції, які треба підтримувати робочими замість однієї, і журнали доставки, що ростуть і потребують чищення; обидві прийнятні, бо пошта — це канал, який платформа не може обійти.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала рівень даних PostgreSQL, побудований насамперед на функціях — 1 275 збережених функцій у 34 схемах — щоб кожне читання й кожен запис проходили через функцію, на яку база даних може видати права, а не через таблицю.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-a-postgresql-function-first-data-layer-across-63/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-a-postgresql-function-first-data-layer-across-63/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Логіка живе в одному місці, яке справді можна перевірити, API лишається тонким і нудним у хорошому сенсі, а межу доступу забезпечує сам Postgres, а не те, що…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Бізнес‑логіка має звичку просочуватися. Частина потрапляє в API, частина — у якийсь SQL, що виконується прямо в обробнику, і незабаром те саме правило виявляється записаним двома‑трьома трохи різними способами, і немає жодного місця, на яке можна вказати й сказати: «ось що система робить зі своїми даними». Так у систему потрапляють баги й діри в безпеці.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Метою було одне місце для всього цього: кожне читання й запис проходить через базу даних, API залишається тонким адаптером, який не знає бізнес‑правил, а все разом можна щільно замкнути.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Рівень даних побудовано за принципом function‑first. Схему поділено за доменами — identity, organization, review, message, notification і ще 29 інших, 34 разом, — і кожна операція, яку може виконати застосунок, є однією з 1 275 функцій PostgreSQL, які він викликає; прямого доступу до таблиць із Go взагалі немає. Далі це забезпечує сама база даних. Роль, під якою логіниться API, mariner, має EXECUTE на функціях застосунку та USAGE на схемах — і нічого більше: жодного SELECT, жодного INSERT, жодного способу торкнутися таблиці напряму — а це виходить приблизно 4 000 явних грантів, а не один загальний. Функції виконуються як SECURITY DEFINER, належать окремій non‑login ролі function_owner із зафіксованим search_path, а обліковий запис суперкористувача лишається зарезервованим для міграцій і cron, подалі від застосунку, що працює.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Логіка живе в одному місці, яке справді можна перевірити, API лишається тонким і нудним у хорошому сенсі, а межу доступу забезпечує сам Postgres, а не те, що всі пам&amp;rsquo;ятають правила. Якщо API раптом буде скомпрометовано, воно все одно не зможе зробити нічого, чого не дозволяють функції. На 1 275 функціях ця дисципліна коштує чогось реального — нове поле означає міграцію та зміну функції, а не рядок у запиті, — і це тертя є ціною того, що межа тримається.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Впровадила deep‑merge на основі каталогу для збережених JSON‑налаштувань, запобігши збоям через відсутні ключі при еволюції схеми.</title>
    <id>https://software.engineer.company/uk/portfolio/implemented-a-catalogue-driven-deep-merge-for-stored-65/</id>
    <link href="https://software.engineer.company/uk/portfolio/implemented-a-catalogue-driven-deep-merge-for-stored-65/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Міграції та модернізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Налаштування можуть зростати без побоювань. Додавання параметра більше не ризикує крашем через undefined-поле на клієнті, а фронтенд перестав потребувати…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа зберігає JSON‑налаштування — налаштування сповіщень і подібне — як збережені значення користувача, накладені поверх набору значень за замовчуванням. Початкове злиття робило це на одному рівні. Проблема виявляється пізніше: додається новий ключ до значень за замовчуванням, а рядки, збережені до появи цього ключа, просто його не мають. Тоді якийсь клієнтський код читає це поле, отримує undefined і падає — саме для тих користувачів, які тут найдовше.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Розвиток схеми налаштувань мав бути безпечним, щоб додавання нового параметра ніколи не ламало людей, які зареєструвалися до того, як він з&amp;rsquo;явився.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Однорівневе злиття замінено на deep‑merge, керований значеннями за замовчуванням як каталогом. Значення за замовчуванням розглядаються як авторитетний перелік усіх ключів, які мають існувати; збережені значення користувача рекурсивно накладаються зверху, тож усе, що є в каталозі, гарантовано присутнє на виході — незалежно від того, чи було воно в збереженому blob. Додається ключ до значень за замовчуванням — і він автоматично з&amp;rsquo;являється в ефективних налаштуваннях кожного наявного рядка, включно з вкладеними ключами. Це впроваджено через міграцію, тож наявні дані отримали перевагу одразу, а не чекали на переписування.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Налаштування можуть зростати без побоювань. Додавання параметра більше не ризикує крашем через undefined‑поле на клієнті, а фронтенд перестав потребувати захисних перевірок, розкиданих у кожному місці, де він читає налаштування. Це також дало решті платформи надійний спосіб розширювати будь‑який збережений JSON‑blob — не лише окреме виправлення, а й сам патерн.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Змоделювала морський домен — фахівців, компанії, судна, вакансії, відгуки та решту — у 348 нормалізованих таблицях у межах 34 схем PostgreSQL, з довідниками SMALLINT та ключами UUID v7.</title>
    <id>https://software.engineer.company/uk/portfolio/modeled-the-maritime-domain-professionals-companies-ships-jobs-67/</id>
    <link href="https://software.engineer.company/uk/portfolio/modeled-the-maritime-domain-professionals-companies-ships-jobs-67/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інженерія даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Результатом стала модель даних, яка є послідовною і швидкою, а працювати з нею передбачувано, бо ті самі правила діють усюди — немає особливих випадків, які…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Серцем платформи є щільний морський домен — фахівці, компанії, судна, вакансії, відгуки, — і всі ці сутності постійно посилаються одна на одну. Фахівець ходить у рейси на суднах, працює в компаніях, залишає відгуки; компанія володіє суднами й публікує вакансії. Майже кожна функція — це запит через усю цю мережу зв&amp;rsquo;язків, тож від того, наскільки добре змодельовані дані, залежить, наскільки добре працює більшість застосунку і наскільки розумно його розширювати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Цей домен потрібно було змоделювати так, щоб він лишався швидким і зберігав цілісність, а додавання наступного типу сутності не перетворювалося на боротьбу зі схемою.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Дані організовано як нормалізовані схеми PostgreSQL, згруповані за доменами, — 348 таблиць у 34 схемах на цей момент. Численні дрібні стабільні переліки — статуси, типи, категорії — перетворено на довідкові таблиці SMALLINT, що робить рядки компактними, а джойни дешевими, замість того щоб зберігати текстові коди всюди. Сутності отримують первинні ключі UUID v7, тож вони глобально унікальні, але водночас часово впорядковані в індексі. Крізь усе проходить одна угода про іменування — таблиці в множині всередині схем з іменами в однині, — застосована без винятків, що як бонус дає змогу уникнути багатьох конфліктів із зарезервованими словами. А зв&amp;rsquo;язки підтримуються реальними foreign key та constraints, тож цілісність — це робота бази даних, а не те, що застосунок мусить пам&amp;rsquo;ятати сам.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Результатом стала модель даних, яка є послідовною і швидкою, а працювати з нею передбачувано, бо ті самі правила діють усюди — немає особливих випадків, які треба запам&amp;rsquo;ятовувати. Додавання функції зазвичай означає розширення схеми за наявною логікою, а не боротьбу проти неї, і це єдина причина, чому 34 схеми — це структура, а не розповзання. Це той фундамент, на якому стоїть решта платформи.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала фронтенд на Next.js 16 зі свідомими стратегіями SSR, SSG і CSR та багаторазовою фабрикою prefetched‑server‑page, що усуває каскад N&#43;1 на кожній автентифікованій сторінці, перенесеній на неї.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-next-js-16-frontend-with-deliberate-73/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-next-js-16-frontend-with-deliberate-73/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сторінки, перенесені на цю фабрику, піднімаються за одне звернення замість шторму звернень, а оскільки це фабрика, а не патерн, який копіюють вручну, наступна…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Автентифікований дашборд мав відчуватися швидким і водночас залишатися по‑справжньому інтерактивним, а ці дві мети тягнуть у різні боки, якщо підійти до них наївно. Якщо забирати все на клієнті, перше завантаження затягується, а гірше — виникає патерн N+1, коли кожен компонент прокидається і робить власний запит, тож одна сторінка перетворюється на каскад мережевих звернень.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Кожну частину застосунку потрібно було рендерити саме так, як їй насправді підходило, не жертвуючи клієнтською інтерактивністю там, де вона мала значення.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Фронтенд на Next.js 16 використовує для кожної поверхні застосунку той режим, який їй підходить, замість одного рішення на всі випадки. Маркетингові й публічні сторінки генеруються статично — вони не змінюються залежно від користувача, тож рендерити їх на кожен запит немає сенсу. Справді інтерактивні частини лишаються клієнтськими. А там, де каскад N+1 справді дошкуляє, — автентифікований дашборд і великі сторінки‑каталоги — рішення винесли у фабрику, а не робили вручну: createPrefetchedServerPage отримує дані сторінки на сервері й передає їх клієнту вже заповненими, тож компоненти одразу з&amp;rsquo;являються зі своїми даними, а не йдуть по них кожен окремо. Стратегія інвалідації кешу задокументована для кожного запиту, тож дані лишаються актуальними без повторного завантаження того, що застосунок уже має.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сторінки, перенесені на цю фабрику, піднімаються за одне звернення замість шторму звернень, а оскільки це фабрика, а не патерн, який копіюють вручну, наступна перенесена сторінка успадковує цю поведінку безкоштовно. Решта автентифікованого застосунку досі рендериться на клієнті й стоїть у черзі за нею — це міграція з робочим механізмом і очевидною наступною сторінкою, а не завершений перехід.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Реалізувала повну підтримку Progressive Web App — з можливістю встановлення та офлайн‑роботи — з кешуванням Workbox під час виконання через next‑pwa.</title>
    <id>https://software.engineer.company/uk/portfolio/delivered-full-progressive-web-app-support-installable-and-74/</id>
    <link href="https://software.engineer.company/uk/portfolio/delivered-full-progressive-web-app-support-installable-and-74/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Користувачі можуть встановити застосунок і продовжувати користуватися ним офлайн, а повторні завантаження швидко повертаються з кешу замість мережі.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Значна частина користувачів платформи перебуває в морі. Моряки та польовий персонал працюють з телефонів, часто офлайн або на нестабільному з&amp;rsquo;єднанні, — це не люди за робочим столом зі стабільним офісним wifi. Якби застосунок будувався так, ніби в усіх є швидка й постійна мережа, це непомітно відсікло б значну частину реальної аудиторії.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Застосунок мав встановлюватися як нативний і залишатися придатним до використання навіть при зникненні мережі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Продукт постачається як повноцінний Progressive Web App. Він встановлюється на головний екран з коректними іконками різних розмірів, екраном заставки та кольорами теми, тож виглядає і запускається як застосунок, а не як закладка. Service worker налаштовано через плагін next‑pwa, а Workbox для runtime‑кешування використовує стратегію CacheFirst для того, що не змінюється від запиту до запиту, — шрифтів, зображень, аудіо, відео, CDN‑ресурсів, — разом з розумними HTTP‑заголовками cache‑control. Оскільки service worker коректно працює лише через HTTPS, тестування на основі HTTPS підтвердило офлайн- та інсталяційну поведінку на реальних пристроях, замість того щоб просто сподіватися, що все спрацює.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Користувачі можуть встановити застосунок і продовжувати користуватися ним офлайн, а повторні завантаження швидко повертаються з кешу замість мережі. Платформа поводиться як нативний застосунок на пристроях, які реально носять із собою користувачі, а для цієї аудиторії це не приємний бонус — це різниця між тим, чи придатний застосунок до використання в морі, чи ні.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала дизайн‑систему iOS 26 &#39;Liquid Glass&#39; та канонічний реєстр компонентів, дотримання якого забезпечували правила лінтингу для запобігання розбіжностям UI.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-an-ios-26-liquid-glass-design-system-75/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-an-ios-26-liquid-glass-design-system-75/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <summary>UI лишається послідовним і відповідним бренду, а одноразові компоненти, які інакше почали б поширюватися, перехоплюються раніше, ніж це стається.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; UI без спільної візуальної мови й фіксованого набору компонентів пливе, і пливе швидко. Кожен новий екран винаходить власні кнопки, бейджі й картки, трохи інакші щоразу, і ці дрібні неузгодженості накопичуються, доки продукт не починає виглядати нецілісним, а будь‑яка зміна означає торкатися п&amp;rsquo;яти саморобних версій одного й того самого.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Дизайн‑система мала бути достатньо цілісною, щоб виглядати продуманою, і достатньо примусовою, щоб не розмиватися в ту мить, коли команда завантажена іншим.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Візуальну мову й систему компонентів було спроєктовано як одне ціле. Мова — це вигляд у стилі iOS 26 «Liquid Glass»: напівпрозорі панелі з розмиттям фону, шаруваті тіні, легка рефракція, пружинні анімації, — побудований на утилітах Tailwind. Над цим стоїть канонічний набір компонентів, з яких має складатися кожен екран: Card, Label, Button, GlassIconButton, DirectoryGrid та інші. Тримається все це завдяки лінтингу: правила відхиляють саморобний бейдж чи чіп і натомість вказують на канонічний компонент, тож систему підтримує інструментарій, а не пам&amp;rsquo;ять того, хто саме цього дня перевіряє код. А документація супроводжується конкретними нотатками «помилка → рішення»: замість абстрактного принципу — приклад неправильного та правильного варіанта.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; UI лишається послідовним і відповідним бренду, а одноразові компоненти, які інакше почали б поширюватися, перехоплюються раніше, ніж це стається. Візуальна узгодженість перестала залежати від дисципліни кожного й стала тим, що утримує інструментарій, — а це єдина версія узгодженості, яка переживає дедлайн.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спроєктувала UI та UX продукту наскрізно — сітки каталогів, подвійні подання картка/таблиця, валідатори вимог у реальному часі та навігацію breadcrumb.</title>
    <id>https://software.engineer.company/uk/portfolio/designed-the-product-s-ui-and-ux-end-76/</id>
    <link href="https://software.engineer.company/uk/portfolio/designed-the-product-s-ui-and-ux-end-76/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>У результаті вийшов вилощений, послідовний досвід, який робить щільні морські дані доступними для сприйняття та проводить людей крізь складні місця.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа показує людям багато різних сутностей — фахівців, компанії, судна, вакансії, відгуки, — і інтерфейс мав поєднувати дві речі, які суперечать одна одній: привабливий вигляд і справжню зручність. Достатньо щільний, щоб показувати реальні морські дані, але не настільки, щоб перетворитися на стіну, об яку розбиваєшся.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; UI та UX продукту було опрацьовано наскрізно — макети, патерни взаємодії та дрібніші речі на кшталт того, як провести людину крізь форму, не змушуючи її відчувати тиск.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Основну роботу виконали кілька рішень. Сітки каталогів мають перемикач картка/таблиця, тож можна переглядати дані візуально або сканувати щільну таблицю, і застосунок пам&amp;rsquo;ятає обраний варіант. Форми використовують живі валідатори вимог, розташовані над полем вводу: кожне правило показується зеленим, коли воно виконане, і жовтогарячим, коли ні, — тож користувача скеровують під час вводу, а не докоряють йому після відправлення. Навігація — це послідовні хлібні крихти та двоколонкові макети сутностей, тож сторінки відчуваються як один продукт, а не набір непов&amp;rsquo;язаних екранів. А філософія помилок — це підказка замість провалу: жодних червоних стін, редиректи замість глухих кутів, застосунок намагається вести користувача далі, а не зупиняти його.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; У результаті вийшов вилощений, послідовний досвід, який робить щільні морські дані доступними для сприйняття та проводить людей крізь складні місця. Він виглядає продуманим і таким, якому можна довіряти, а на платформі, яку люди використовують для власної кар&amp;rsquo;єри, це не просто косметика: якщо все виглядало б недбало, вони довіряли б даним менше, і мали б рацію.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Посилила захист застосунку за допомогою CSP на основі nonce, HSTS, cookie SameSite, ролей бази даних за принципом найменших привілеїв та серверних повторних перевірок прав доступу.</title>
    <id>https://software.engineer.company/uk/portfolio/hardened-the-application-with-nonce-based-csp-hsts-77/</id>
    <link href="https://software.engineer.company/uk/portfolio/hardened-the-application-with-nonce-based-csp-hsts-77/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <summary>Безпека не залежить від того, як поводиться UI. Захист побудовано шарами так, щоб подолання одного рівня не давало проходу через решту, а вся система базується…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа зберігає професійні та організаційні дані — саме ті, які люди очікують бачити захищеними належним чином, тож одного рубежу оборони було апріорі недостатньо. Робоче припущення таке: клієнт вороже налаштований, — усе, що примусово виконує браузер, може бути вимкнене тим, у чиїх руках цей браузер, — і безпека все одно мусить триматися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Платформу потрібно було захистити на кожному рівні — фронтенд, API, база даних, — так, щоб безпеку забезпечував сервер незалежно від того, що саме дозволяв інтерфейс.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; На фронтенді проксі‑мідлвар Next.js — proxy.ts — встановлює Content‑Security‑Policy з nonce для кожного запиту та strict‑dynamic, а також HSTS і SameSite cookies, тож браузер жорстко обмежений у тому, що він виконає й надішле. На рівні API діють rate limiting, CORS, обмеження розміру запиту, валідація вводу до того, як щось торкнеться бази даних, і логування подій, пов&amp;rsquo;язаних із безпекою. У базі даних API входить під роллю з мінімальними привілеями, яка може лише виконувати (EXECUTE) функції застосунку, самі функції запускаються з SECURITY DEFINER, а все параметризовано. А права доступу — тариф, роль, організація, прив&amp;rsquo;язка до судна — перевіряються сервером повторно на кожен запит, тоді як фронтендні обмеження розглядаються лише як UX. Ці обмеження визначають, що видно; сервер визначає, що дозволено робити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Безпека не залежить від того, як поводиться UI. Захист побудовано шарами так, щоб подолання одного рівня не давало проходу через решту, а вся система базується на припущенні, що клієнту довіряти не можна, — і це правильне припущення для даних, які люди довіряють платформі.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Створила систему інтернаціоналізації для англійської та данської мов, що несе 12 027 повідомлень на локаль у 458 файлах namespace, зі словником, дотримання якого забезпечував лінтер, та бюджетом у 400 рядків на файл.</title>
    <id>https://software.engineer.company/uk/portfolio/established-an-english-danish-internationalization-system-with-linter-78/</id>
    <link href="https://software.engineer.company/uk/portfolio/established-an-english-danish-internationalization-system-with-linter-78/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Обидві локалі лишаються коректними й узгодженими на 24 054 повідомленнях між ними, а файли лишаються придатними до підтримки навіть у міру зростання кількості…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа працює англійською та данською, а системи перекладу мають властивість розповзатися в хаос. Файли ростуть без обмежень, ключі протікають — присутні в одній локалі й відсутні в іншій, — а мовно‑специфічні конвенції застосовуються нерівномірно, тож одна з локалей зрештою читається так, ніби її перекладав комітет, учасники якого між собою не спілкувалися. Для професійного продукту це не дрібна вада — це виглядає як недбалість.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Налаштування інтернаціоналізації мало масштабуватися — утримувати обидві мови узгодженими й коректними, а файли — придатними для підтримки людиною навіть через рік.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Систему побудовано на next‑intl з правилами, які інструментарій справді примусово застосовує. Данська сторона має зафіксований словник і стиль — буквальні æøå, неформальне звертання «du», правильні наголоси в наказовому способі та семантичні відповідники для складних іменників, щоб їх перекладали за змістом, а не дослівно, — і лінтер стежить за цим. Діє жорсткий ліміт у 400 рядків на файл namespace, з підходом split‑and‑merge: велика область ділиться на вкладені файли, які потім чисто зливаються назад, замість того щоб один файл ріс нескінченно; саме через цей ліміт 12 027 повідомлень на локаль живуть у 458 файлах, а не в кількох величезних. Лінтер‑перевірка звіряє ключі між локалями, тож нічого не протікає і не губиться. А збережені overrides зливаються на основі каталогу, а не через крихкі фолбеки верхнього рівня — та сама ідея deep‑merge, що використовується для налаштувань.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Обидві локалі лишаються коректними й узгодженими на 24 054 повідомленнях між ними, а файли лишаються придатними до підтримки навіть у міру зростання кількості рядків. Якість мови стала тим, що інструментарій гарантує на кожному коміті, а не тим, що непомітно псується щоразу, коли хтось поспіхом додає рядок. Саме ліміт є несучою конструкцією: без обмеження на файл замість 458 файлів було б дванадцять, і ніхто б їх не відкривав.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Заклала засадничі рішення платформи в тижні після відкриття репозиторію в листопаді 2025 року — поділ на рівні, доступ до даних передусім через базу даних та планку без жодних попереджень — і вони тримаються дев&#39;ять місяців потому.</title>
    <id>https://software.engineer.company/uk/portfolio/set-the-platform-s-founding-decisions-in-november-2025-80/</id>
    <link href="https://software.engineer.company/uk/portfolio/set-the-platform-s-founding-decisions-in-november-2025-80/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Керівництво командою" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Технічне лідерство" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Через дев&#39;ять місяців і кілька тисяч комітів усі три тримаються: рівні не розмилися, жоден обробник не звертається до таблиці напряму, а білд і досі не має…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Репозиторій відкрито 25 листопада 2025 року, і в ньому не було нічого. Те, що вирішується в перші кілька тижнів такого проєкту, має непропорційну вагу: поділ на рівні, місце, де дозволено жити бізнес‑логіці, планка якості. Такі рішення дешево ухвалювати на третій день і майже неможливо скасувати на шостий місяць, бо на той момент усе написане відтоді вже на них спирається.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Засадничі рішення мали бути ухвалені свідомо й рано, причому в такій формі, щоб вони пережили передачу іншим людям і кодовій базі, значно більшій за ту, що існувала на той час.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Основну роботу зробили три рішення. Стек поділено на рівні так, щоб кожна частина мала одну роботу — фронтенд на Next.js, Go API, який валідує й передає далі, рівень функцій PostgreSQL, якому належать бізнес‑правила, — замість того щоб логіка опинялася там, де було зручно того дня. Доступ до даних із самого початку сховано за збереженими функціями, і саме з цього рішення випливає все інше, що стосується бази даних; впровадити його заднім числом означало б переписати кожен обробник. А планку нульових попереджень запроваджено ще до того, як з&amp;rsquo;явилося багато коду, який треба їй підпорядкувати, бо стандарт, уведений на коміті 5 000, — це проєкт із прибирання, тоді як той самий стандарт на коміті 50 — це просто те, як працює репозиторій. Жодне з цих трьох рішень не було легким варіантом на той момент, і всі три коштували темпу в перший місяць.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Через дев&amp;rsquo;ять місяців і кілька тисяч комітів усі три тримаються: рівні не розмилися, жоден обробник не звертається до таблиці напряму, а білд і досі не має жодного попередження. Саме таку перевірку варто застосовувати до засадничого рішення — не чи звучало воно правильно, а чи пережило воно зіткнення з обсягом роботи, що прийшов далі, бо саме в цій точці зручні рішення зазвичай тихо полишають.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Розробляла та підтримувала вебзастосунки на Django для IPTV‑платформи, постачаючи нові функції та покращуючи продуктивність і стабільність.</title>
    <id>https://software.engineer.company/uk/portfolio/developed-and-maintained-django-web-applications-for-the-84/</id>
    <link href="https://software.engineer.company/uk/portfolio/developed-and-maintained-django-web-applications-for-the-84/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Застосунки продовжували набувати можливостей, лишаючись при цьому надійними і для внутрішніх команд, і для клієнтів.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Навколо IPTV‑платформи існували вебзастосунки на Django — саме та частина, на яку люди реально натискали, — і вони мали продовжувати рухатися вперед: нові функції, а також продуктивність і стабільність, яких вимагає платформа, що працює цілодобово.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб ці застосунки лишалися багатофункціональними, швидкими й стабільними.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Вебзастосунки на Django розроблялися й підтримувалися — нові функції створювалися, помилки виправлялися, а робота над продуктивністю та стабільністю велася разом з усією командою, а не в окремому кутку. У чомусь, що безперервно обслуговує клієнтів, стабільність — це не приємний додаток до функцій, а обмеження, якому функції мусять підпорядковуватися. Ефектна функція, через яку все хитається, не варта багато, коли хитатися не можна.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Застосунки продовжували набувати можливостей, лишаючись при цьому надійними і для внутрішніх команд, і для клієнтів. Додавати щось нове, не дестабілізуючи систему, — ось баланс, який тут мав значення, і саме його дотримувалася робота.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Планувала та впроваджувала нову функціональність інфраструктури для внутрішніх і зовнішніх систем, створюючи рішення, достатньо довговічні, щоб працювати роками з мінімальними змінами.</title>
    <id>https://software.engineer.company/uk/portfolio/planned-and-implemented-new-infrastructure-functionality-for-internal-85/</id>
    <link href="https://software.engineer.company/uk/portfolio/planned-and-implemented-new-infrastructure-functionality-for-internal-85/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <summary>Системи залишалися функціональними та ефективними ще довго після їх побудови, працюючи роками майже без змін.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; У міру зростання організації її внутрішні та зовнішні системи постійно потребували нових можливостей, які додавалися нашвидкуруч. Найпростіший спосіб зробити це — обрати те, що найшвидше сьогодні; проблема простого шляху в тому, що вже за півроку доводиться повертатися й усе переробляти.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб спланувати та побудувати інфраструктурну функціональність, яка справді витримає перевірку часом, — не просто працювати зараз, а продовжувати працювати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Нову інфраструктурну функціональність було сплановано та впроваджено у внутрішніх і зовнішніх системах з розрахунком на довговічність — саме той тип рішень, які будують один раз і правильно, щоб вони роками працювали з мінімальним втручанням, а не вимагали постійної уваги. Це свідомий вибір щоразу: витратити трохи більше часу на роздуми на старті, щоб не приректи себе на вічне «нянькання» з результатом.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Системи залишалися функціональними та ефективними ще довго після їх побудови, працюючи роками майже без змін. Саме така довговічність і є справжнім мірилом інфраструктурної роботи — зробити щось, що працює сьогодні, може будь‑хто; зробити щось, що тихо продовжує працювати через роки, — завдання значно складніше й цінніше.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Як одна з перших співробітниць, спроєктувала та побудувала всю базову інфраструктуру та супутні процеси з нуля для SaaS‑стартапу в зеленій енергетиці, заклавши фундамент для швидкого зростання.</title>
    <id>https://software.engineer.company/uk/portfolio/as-one-of-the-first-hires-designed-and-86/</id>
    <link href="https://software.engineer.company/uk/portfolio/as-one-of-the-first-hires-designed-and-86/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Cloud" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <category term="Хмарна інфраструктура та міграція" scheme="https://software.engineer.company/uk/services/" />
    <summary>Стартап отримав міцну технічну основу, і саме вона дала бізнесу змогу згодом швидко зростати. Бути тим, хто будує таку основу з нуля, — це особлива…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Це був SaaS‑стартап у сфері зеленої енергетики — з перспективною ідеєю, але практично без технічної основи під нею. Прихід на посаду одним із перших співробітників означав той етап, коли підтримувати ще нічого, бо нічого ще не існує, — закладання ґрунту, на якому згодом стоятимуть усі інші.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завданням було з нуля побудувати основну інфраструктуру та процеси навколо неї.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було спроєктовано та побудовано всю базову інфраструктуру й супутні процеси — сервери, мережі, потоки даних, безпеку, операційну складову. У стартапі це означає ухвалення рішень, які потім важко скасувати, тож мета полягала не просто в тому, щоб «щось запрацювало», а в тому, щоб закласти фундамент, здатний витримати вагу швидкого зростання без потреби зривати все й переробляти в момент, коли компанія стане більшою. Ранні інфраструктурні рішення або стають тим, що дає змогу масштабуватися, або тим, що потім рік доводиться розбирати; мета однозначно була в першому.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Стартап отримав міцну технічну основу, і саме вона дала бізнесу змогу згодом швидко зростати. Бути тим, хто будує таку основу з нуля, — це особлива відповідальність: зроби правильно — і ніхто не помітить, зроби неправильно — і помітять усі, — і в цьому випадку основа витримала.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Підтримувала та вдосконалювала застарілий сайт на Hugo, водночас долучаючись до покращень UI/UX основного продукту з управління активами.</title>
    <id>https://software.engineer.company/uk/portfolio/maintained-and-enhanced-the-legacy-hugo-static-site-87/</id>
    <link href="https://software.engineer.company/uk/portfolio/maintained-and-enhanced-the-legacy-hugo-static-site-87/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Вебсайт залишався актуальним, а не тихо старів, а зручність використання основного продукту зростала завдяки послідовному, усвідомленому вдосконаленню — тому,…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Існував застарілий вебсайт, побудований на Hugo — генераторі статичних сайтів, — який працював паралельно з основним продуктом компанії, системою управління активами. Вебсайт був тим давнім, усталеним елементом; а реальна цінність була зосереджена в продукті.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб підтримувати сайт у робочому стані й водночас покращувати досвід користування продуктом.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Статичний сайт на Hugo підтримувався й вдосконалювався — залишався актуальним і працездатним, — тоді як покращення UI/UX і зворотний зв&amp;rsquo;язок водночас спрямовувалися в основний продукт управління активами. Розподіл уваги між застарілим сайтом і флагманським продуктом — це насамперед про те, щоб не дати старому занепасти, поки увага прикута до нового; обидва так чи інакше представляли компанію перед кимось, тож обидва мали залишатися в належному стані.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Вебсайт залишався актуальним, а не тихо старів, а зручність використання основного продукту зростала завдяки послідовному, усвідомленому вдосконаленню — тому, яке народжується з реального використання й обдумування продукту, а не з одного великого редизайну.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Забезпечила успіх клієнтів у вебі, поєднавши розробку та дизайн індивідуальних вебсайтів із SEO, контент‑стратегією та копірайтингом.</title>
    <id>https://software.engineer.company/uk/portfolio/drove-client-web-success-by-combining-custom-website-91/</id>
    <link href="https://software.engineer.company/uk/portfolio/drove-client-web-success-by-combining-custom-website-91/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бренд і маркетинг" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Клієнти отримали вищу видимість і більше залучення — їхні сайти працювали як справжні канали зростання, а не як онлайн-буклети.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Клієнтам насправді потрібен був не вебсайт сам по собі — їм потрібно було те, що вебсайт має для них робити: щоб його знаходили, щоб він приваблював клієнтів, щоб він справді працював як канал. Гарний сайт, який ніхто не може знайти, — це провал, що маскується під успіх.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Завдання полягало в тому, щоб об&amp;rsquo;єднати розробку та зростання в одну пропозицію, а не просто передати клієнту готовий сайт і побажати удачі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Було об&amp;rsquo;єднано дві складові — розробку та дизайн вебсайтів на замовлення з одного боку, SEO, контент‑стратегію та копірайтинг з іншого, — щоб клієнт отримував продукт, який був водночас якісно побудований і справді помітний у пошуку. Зазвичай це вважають окремими завданнями, тому й з&amp;rsquo;являються то чудові сайти, яких немає в жодній видачі, то добре оптимізовані сайти, якими неприємно користуватися. Поєднання обох напрямів означало, що сайт із самого початку проєктувався так, щоб його знаходили, а не оптимізувався заднім числом.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Клієнти отримали вищу видимість і більше залучення — їхні сайти працювали як справжні канали зростання, а не як онлайн‑буклети. Саме поєднання розробки та пошукової доступності в одному процесі перетворило вебсайт із витрати на те, що дійсно окупало себе.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала багаторівневий набір автоматизованих тестів — 981 тест Go, 543 фронтендні та браузерні специфікації, 494 поведінкові тести SQL — з мутаційним тестуванням, property‑based тестами та обов&#39;язковою перевіркою доступності.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-layered-automated-test-suite-across-four-layers-94/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-layered-automated-test-suite-across-four-layers-94/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Змінювати щось структурне перестало бути страшно, а це єдине, що не дає кодовій базі такого розміру закам&#39;яніти.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Платформа, що тримає свою бізнес‑логіку в базі даних, має проблему з тестуванням, якої немає в більшості проєктів. Логіка написана не тією мовою, з якою добре працює тестовий фреймворк, — вона в SQL, за фасадом функцій, а SQL — це саме той код, який лишається непокритим, бо тестувати його незручно. Якщо зверху додати API на Go та фронтенд на Next.js, «важливі частини покрито» тихо перетворюється на «покрито ті частини, які було легко покрити».&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Кожен рівень мав отримати перевірку своєї поведінки там, де ця поведінка насправді живе, а не так, щоб усе перевірялося ззовні через браузер.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Чотири рівні отримали чотири види тестів. API на Go несе 981 тестову функцію в 310 файлах. Фронтенд несе 543 spec‑файли Vitest і Playwright, зокрема 48 end‑to‑end файлів і 30 браузерних spec‑файлів. База даних несе 494 файли поведінкових тестів — 116 876 рядків SQL, які перевіряють свої припущення через 6 654 згенеровані винятки, — тож збережена функція тестується в самій базі даних, а не крізь три рівні застосунку над нею. Над ними стоять тести, що тестують тести: мутаційне тестування Stryker навмисно ламає рядок коду й падає, коли цього ніхто не помічає, а fast‑check генерує вхідні дані, які нікому не спало на думку записати. Гейт на axe‑core вимагає нуля порушень WCAG 2.0 і 2.1 рівнів A та AA, тож доступність стає падінням білду, а не знахідкою аудиту через кілька місяців. Пороги покриття рухаються лише вгору. Увесь набір виконується як 10 задач у workflow на 612 рядків.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Змінювати щось структурне перестало бути страшно, а це єдине, що не дає кодовій базі такого розміру закам&amp;rsquo;яніти. Чесна ціна — це час: набір повільний, він оподатковує кожну зміну, і на такому масштабі сам потребує підтримки. Натомість він дає можливість і далі рухатися швидко, і вона варта більше, ніж ті хвилини, які він забирає.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала рівень платежів і прав доступу — Stripe поряд із внутрішньозастосунковими покупками Apple і Google — обмеживши каталог, пошук та експорт моделлю доступу з 11 таблиць, яку перевіряє сервер.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-payments-and-entitlements-layer-96/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-payments-and-entitlements-layer-96/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Додавання вітрини тепер зачіпає бік payments і лишає гейти в спокої, а питання підтримки про чийсь доступ має одну таблицю, у яку треба зазирнути, замість…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Гроші — це та частина платформи, до якої нікому не дозволено ставитися недбало. Підписка мусить пережити закінчення строку дії картки, повернення коштів, зміну тарифу, вебхук, що прийшов двічі, і вебхук, що прийшов не в тому порядку. Щойно оплата починає відбуватися на трьох вітринах — карткою у вебі, через Apple в одному app store, через Google в іншому, — з&amp;rsquo;являються три різні версії того, що саме людина купила, а продуктові все одно потрібна одна відповідь на одне запитання: що цій людині дозволено робити просто зараз?&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Приймання грошей і надання прав мали стати двома системами, а не однією, щоб додавання ще однієї вітрини не означало переписування кожного гейта в продукті.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Stripe опрацьовує картки й підписки через 18 файлів Go, а in‑app‑покупки Apple і Google приходять через власну перевірку квитанцій. Усі три сходяться в схемі payments із 9 таблиць і 34 функцій — і на цьому спиняються. Те, про що продукт запитує насправді, — це окрема схема access, 11 таблиць і 34 функції, яка відповідає на «чи можна цьому обліковому запису зробити це?», не знаючи й не цікавлячись, яка саме вітрина за це заплатила. Ця відповідь закриває каталог компаній, пошук і експорт даних, і вона перевіряється сервером повторно на кожен запит, бо прихована кнопка — це ввічливість, а не механізм контролю.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Додавання вітрини тепер зачіпає бік payments і лишає гейти в спокої, а питання підтримки про чийсь доступ має одну таблицю, у яку треба зазирнути, замість трьох. Ціна — це дві схеми там, де меншому продуктові вистачило б однієї, плюс перевірка прав на тих запитах, які інакше були б безкоштовними.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Перенесла повільну роботу зі шляху запиту в чергу завдань River — 15 модулів воркерів, 8 запланованих задач та 20 завдань pg_cron — щоб запит повертався, поки робота за ним триває.</title>
    <id>https://software.engineer.company/uk/portfolio/moved-slow-work-onto-a-river-job-queue-97/</id>
    <link href="https://software.engineer.company/uk/portfolio/moved-slow-work-onto-a-river-job-queue-97/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Запити повертаються швидко, а повільна робота все одно доходить до кінця — з повторними спробами й видимою історією, коли не доходить.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Частині роботи взагалі нема чого відбуватися, поки користувач чекає. Надіслати лист, перебудувати пошуковий індекс, згенерувати документ, перерахувати рейтинги — якщо робити будь‑що з цього всередині запиту, користувач дивиться на спінер заради того, чого ніколи не просив показувати. А якщо робити це в горутині, воно зникає тієї ж миті, коли процес перезапускається, — а він перезапуститься, посеред розгортання, не лишивши й сліду про те, що це взагалі мало статися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Фоновій роботі потрібне було довговічне місце для життя: черга, яка переживає перезапуск, повторює невдалу спробу і в яку можна зазирнути, коли щось не сталося.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Вибір упав на River — переважно тому, що він тримає свою чергу в PostgreSQL: база даних і так є авторитетним джерелом даних, тож задача і рядки, яких вона торкається, комітяться або відкочуються разом, і немає другого шматка інфраструктури, який треба запускати й тримати в голові. За ним стоять 15 модулів‑воркерів і 8 запланованих задач. Нижче 20 задач pg_cron виконують ту підтримку, яку базі даних зручніше робити самій: підчищати партиції, ротувати солі, оновлювати агрегати. Усе, що було достатньо повільним, щоб це помітили, перенесено зі шляху запиту на одне з цих двох.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Запити повертаються швидко, а повільна робота все одно доходить до кінця — з повторними спробами й видимою історією, коли не доходить. Тримати чергу в Postgres, а не у виділеному брокері, — це свідоме обмеження: воно не масштабуватиметься вічно, і на якомусь обсязі стає неправильною відповіддю. Для платформи, вузьким місцем якої і так є база даних, на одну рухому частину менше виявилося вартіснішим за запас, яким однаково не скористалися б.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала власний моніторинг помилок та трасування OpenTelemetry замість покупних — очищення payload, виявлення сплесків і регресій, символікацію та синтетичний heartbeat — за 11 операторськими поданнями.</title>
    <id>https://software.engineer.company/uk/portfolio/built-first-party-error-monitoring-and-tracing-98/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-first-party-error-monitoring-and-tracing-98/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Моніторинг та observability" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Помилки перетворюються на чергу, яку хтось може розібрати, а регресія оголошує про себе сама, замість того щоб її знайшов користувач.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Різниця між платформою, яка піднята, і платформою, яка працює, полягає в тому, чи хтось про це дізнається. Помилка, на яку користувач наштовхнувся об одинадцятій вечора, на сторінці, яку ніхто не тестує, лишається невидимою, доки щось не піде й не збере її. Звична відповідь — купити хостований трекер помилок, і це хороша відповідь, — а ще вона означає, що власні помилки платформи, стектрейси й контекст користувача їдуть до третьої сторони.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Помилки й трейси треба було збирати, групувати й робити придатними до дії так, щоб нутрощі платформи не залишали платформу.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Побудовано дві частини. OpenTelemetry відповідає за трасування через OTLP, тож повільний запит можна простежити наскрізь через фронтенд, API та базу даних, а не здогадуватися про нього. Поруч стоїть власний пайплайн помилок — сервіс errmon і сервіс ingest, — який санітизує payload перед збереженням, групує помилки у повторювані проблеми замість плаского списку, виявляє сплески й регресії з періодом очікування, щоб один невдалий деплой не смикнув когось сорок разів, перетворює мінімізовані стектрейси фронтенду назад на читабельний код і запускає синтетичний heartbeat, щоб довести, що сам пайплайн живий. Усе це осідає в базі даних як події помилок, групи помилок, inbox, латентність API та семпли стеків, а назовні виходить через 11 операторських подань, зокрема одне для service level objectives.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Помилки перетворюються на чергу, яку хтось може розібрати, а регресія оголошує про себе сама, замість того щоб її знайшов користувач. Побудувати замість купити коштувало реального часу й означає, що це ще одна річ на підтримці, — куплений трекер працював би вже того ж дня по обіді. Натомість це дало те, що нічого чутливого не виїжджає назовні, а правила сповіщень підігнані під цю платформу, а не під якусь загальну.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала засоби протидії зловживанням за принципом fail‑closed — 22 обмежувачі частоти на Redis, Cloudflare Turnstile, ідемпотентність запитів та прив&#39;язку до origin — щоб платформа відсікала ботів і напливи, а не довіряла тим, хто її викликає.</title>
    <id>https://software.engineer.company/uk/portfolio/built-fail-closed-abuse-controls-and-rate-limiting-100/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-fail-closed-abuse-controls-and-rate-limiting-100/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Мережі та VPN" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Зловживання стає дорогим для того, хто зловживає, і дешевим для платформи, а збій у власному сховищі обмежувача деградує до відмови, а не до відчинених дверей.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Публічний каталог компаній і фахівців стає мішенню того самого дня, коли виходить у світ. Скраперам потрібні дані, спам‑акаунтам — охоплення, а ендпоінтом, обслуговування якого коштує платформі реальних грошей — пошук, експорт, будь‑що, що торкається зовнішнього API, — варто зловживати вже тому, що викликати його безкоштовно. Нічого з цього не є злим наміром, спрямованим саме проти цієї платформи; це фонова погода відкритого інтернету.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Дорогим і вразливим до зловживань шляхам потрібні були обмеження, які тримають під тиском, зокрема під тиском недоступності власної залежності обмежувача.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Обмежувачів частоти запитів тут 22, і кожен сконструйований під той шлях, який він захищає, замість одного глобального ліміту, бо спроба входу, пошук і масовий експорт стають зловживанням на кардинально різних швидкостях. Стан живе в Redis, тож ліміт спільний для всіх інстансів, а не існує окремо в кожному процесі, звідки його тривіально обійти. Важливе рішення — що відбувається, коли Redis недоступний: обмежувачі закриваються (fail closed). Трафік відхиляється, а не пропускається помахом руки, — це менш зручна відповідь і єдина, яку можна відстояти. Навколо них стоять Cloudflare Turnstile на шляхах, які варто перевіряти челенджем, 351 рядок мідлвару ідемпотентності, щоб повторений запис не перетворився на два, origin‑lock, що відкидає запити, які прийшли не через парадні двері, і власний челендж на самому каталозі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Зловживання стає дорогим для того, хто зловживає, і дешевим для платформи, а збій у власному сховищі обмежувача деградує до відмови, а не до відчинених дверей. Закриватися при збої справді означає, що проблема з Redis стає проблемою, видимою користувачам, — і це прийнято свідомо, бо альтернатива в тому, що проблема з Redis стає проблемою з рахунками.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала операторський бек‑офіс — близько 40 адміністративних маршрутів та 128 компонентів, що охоплюють заявки на володіння, модерацію, feature flags, кеш і діагностику, — щоб платформою можна було керувати без доступу до бази даних.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-operator-back-office-for-the-platform-102/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-operator-back-office-for-the-platform-102/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>Люди, які керують платформою, справді можуть нею керувати, а кожна дія проходить через ту саму авторизацію й лишає той самий слід, що й будь-яка інша.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Кожна платформа непомітно вирощує другий застосунок, і зазвичай це саме той, якого ніхто не планує. Комусь треба схвалити заявку на володіння, приховати відгук, увімкнути функцію для частини користувачів, очистити кеш або з&amp;rsquo;ясувати, чому один обліковий запис бачить щось дивне. Коли такого застосунку немає, відповіддю стає інженер із консоллю бази даних — а це повільно, ніде не логується і за одну одруківку від інциденту.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Керувати платформою щодня мало бути можливо без shell, щоб операційна робота належала тому, хто на зміні, а не тому, у кого є облікові дані.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Бек‑офіс склав приблизно 40 адміністративних маршрутів, побудованих зі 128 компонентів, і охоплює роботу такою, якою вона реально надходить: розгляд заявок на володіння компаніями, модерація відгуків і дописів, перемикання feature flags, перегляд і очищення кешів, читання діагностики та звітність, яку просить CEO. Він працює на тій самій дизайн‑системі й тому самому згенерованому API‑клієнті, що й публічний продукт, — і це був вирішальний вибір: внутрішній інструмент, побудований на власному стеку, стає тією частиною, яку ніхто не оновлює, а далі — тією, якій ніхто не довіряє.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Люди, які керують платформою, справді можуть нею керувати, а кожна дія проходить через ту саму авторизацію й лишає той самий слід, що й будь‑яка інша. Це велика поверхня, яку треба тримати протестованою й доступною заради невеликої внутрішньої аудиторії, і ця ціна платиться постійно. Вона все одно менша за альтернативу — інженера, який о дев&amp;rsquo;ятій вечора в неділю набирає UPDATE на продакшні.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала наскрізний процес заявок на володіння компанією — користувач заявляє права на компанію, адміністратор ухвалює рішення, а схвалення переписує граф авторизації, який визначає, кому що дозволено редагувати.</title>
    <id>https://software.engineer.company/uk/portfolio/built-company-ownership-claims-end-to-end-103/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-company-ownership-claims-end-to-end-103/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>Компанії можуть перебрати й виправити власні записи без того, щоб хтось редагував базу даних вручну, а кожне надання повноважень має названого схвалювача й…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Каталог, наповнений із публічних джерел, має структурну проблему: компанії опинилися в ньому не з власної волі. Рано чи пізно приходить хтось із такої компанії й хоче виправити її запис — а між цією людиною й цим записом немає жодного зв&amp;rsquo;язку, є лише твердження, що зв&amp;rsquo;язок існує. Надати права надто легко — і вашу сторінку редагує конкурент. Надати надто повільно — і каталог лишається неправильним.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Мав існувати шлях від «це моя компанія» до справжніх повноважень над записом — з людським рішенням посередині й слідом позаду.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Заявки на володіння побудовано наскрізно — 108 комітів і обидва застосунки. Користувач подає заявку з доказами; вона потрапляє в чергу в бек‑офісі; адміністратор розглядає її та схвалює або відхиляє з причиною, яка повертається заявникові. Найцікавіше — що саме робить схвалення: це не прапорець у рядку. Схвалення переписує граф авторизації, тож обліковий запис отримує реальний зв&amp;rsquo;язок з організацією — той самий зв&amp;rsquo;язок, до якого вже звертається кожна перевірка прав на платформі. Воротами є рішення людини, а не гілка в коді, і жодній функції не довелося дізнаватися про заявки, щоб ці ворота поважати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Компанії можуть перебрати й виправити власні записи без того, щоб хтось редагував базу даних вручну, а кожне надання повноважень має названого схвалювача й прикріплену причину. Людський розгляд є вузьким місцем за задумом; автоматична перевірка доменного імені була б швидшою — і помилялася б саме в тих випадках, які важать найбільше.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала систему лояльності та репутації — 67 функцій над реєстром із 31 таблиці, з лігами, бейджами та крамницею обміну — де блокування рядка балансу закриває вікно подвійного витрачання.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-loyalty-and-reputation-system-105/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-loyalty-and-reputation-system-105/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Внесок вимірюється й винагороджується, а баланс — це арифметика, а не наближення. Блокування рядка — повільніша відповідь, і його все одно обрано: конкуренція…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Професійний нетворкінг має проблему холодного старту: платформою варто користуватися тоді, коли нею вже користуються інші, а доти майже немає причин повертатися. Звичний важіль — це система винагород: бали за внесок, статус, що відображає репутацію. Описати її легко, а побудувати підступно, бо щойно бали можна витратити, вони стають грішми, і кожна помилка, якої припускаються з грішми, доступна й тут.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Внесок мав бути вимірюваним і винагороджуваним, а баланс — таким, який не можна витратити двічі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Схема лояльності налічує 31 таблицю та 67 функцій, статус — ще 5 таблиць і 32 функції, а поруч стоять схеми discovery й персоналізації, які вирішують, що саме бачить конкретний учасник. Над реєстром надбудовані ліги, бейджі та крамниця обміну, де баланс перетворюється на щось реальне. Найбільше уваги забрав найдавніший баг у світі: перевірити баланс, потім списати його — і два запити, що прийшли одночасно, обидва проходять перевірку. Кожна мутація бере блокування рядка гаманця, перш ніж його прочитати, тож другий запит чекає на завершення першого, а не змагається з ним. І те, що гаманець лежить у тій самій базі даних, що й усе інше, — саме це взагалі робить таке можливим: баланс і те, що на нього куплено, комітяться разом або не комітяться зовсім.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Внесок вимірюється й винагороджується, а баланс — це арифметика, а не наближення. Блокування рядка — повільніша відповідь, і його все одно обрано: конкуренція за гаманець — це черга, а альтернатива — учасник, який витрачає ті самі бали двічі, і хтось, хто потім звіряє це вручну.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала соціальний рівень платформи — дописи, стрічку, групи, згадки, граф підписників та дайджест подій — на тому самому рівні даних, побудованому насамперед на функціях, що й решта продукту.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-platform-s-social-layer-106/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-platform-s-social-layer-106/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <summary>У платформи з&#39;явилася причина бути відкритою в день, коли нікому не треба шукати компанію, і з&#39;явилася без паралельного стеку, який довелося б підтримувати.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Каталог компаній — це довідник. Люди зазирають у нього й ідуть. Повертатися на професійну платформу змушує присутність інших людей, а це означає дописи, групи й причину повернутися, яка не зводиться до листа з нагадуванням.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Соціальний рівень треба було додати так, щоб він не став другою системою з власними правилами, власними дозволами та власним способом зберігати дані.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Дописи, стрічка, групи, згадки, граф підписників і дайджест подій зайшли в продукт за 188 комітів — усе на тому самому рівні даних, побудованому насамперед на функціях, що й решта платформи. Це обмеження зробило більшу частину роботи: граф підписників — це такі самі таблиці й функції, як усе інше, згадка розв&amp;rsquo;язується через ту саму схему identity, яку використовує каталог, а допис успадковує чергу модерації, уже побудовану для відгуків. Нічому тут не знадобилося власне сховище чи власна модель дозволів. Єдине місце, яке чинило опір, — це стрічка, бо ефективно зібрати персоналізовану стрічку подій справді інша задача, ніж дістати рядок, і саме тут робота з персоналізації та discovery виправдовує своє місце.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; У платформи з&amp;rsquo;явилася причина бути відкритою в день, коли нікому не треба шукати компанію, і з&amp;rsquo;явилася без паралельного стеку, який довелося б підтримувати. Чи є соціальний рівень правильною інвестицією для морського каталогу — це продуктове питання, а не інженерне: він тут, бо цього попросив продукт, і побудований так само, як усе навколо нього.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала майданчик найму та кар&#39;єрний робочий простір для моряків — 151 збережена функція у 48 таблицях — що охоплюють вакансії, заявки, сертифікати, просування в рангах та підтверджений стаж плавання.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-hiring-marketplace-and-career-workspace-107/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-hiring-marketplace-and-career-workspace-107/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="PostgreSQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Вакансію можна зіставити із задокументованою кваліфікацією, а не з назвою посади, яку людина написала про себе сама, — і саме в цьому вся різниця між дошкою…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Комерційний аргумент на користь морської професійної мережі — це найм: компаніям потрібні екіпажі та офіцери, а морякам потрібні посади на суднах. Обидві половини вже існували на платформі, але не в тій формі — компанії були в каталозі, фахівці мали профілі, і ніщо не поєднувало вакансію з людиною, кваліфікованою її закрити. Найскладніше — саме кваліфікація, бо в цій галузі це сертифікати, ранги й задокументований стаж плавання, а не назва посади.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Вакансії, заявки та перевірювані кваліфікаційні документи моряків потрібно було змоделювати належно, а не як вільний текст у профілі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Побудовано два домени. Сторона найму налічує 32 таблиці та 118 функцій і охоплює вакансії, заявки, формування короткого списку та погляд роботодавця на весь потік кандидатів. Кар&amp;rsquo;єрний робочий простір несе 16 таблиць і 33 функції, у яких зберігаються сертифікати, просування в рангах і стаж плавання, разом із завантаженням документів і чергою ручної перевірки, щоб кваліфікацію було перевірено, а не просто задекларовано. Саме моделювання просування як графа, а не списку, робить зіставлення корисним: одного рангу можна досягти з іншого за наявності певних сертифікатів і достатнього зафіксованого часу в морі, і саме ця структура дає змогу зіставляти вакансію з кар&amp;rsquo;єрою, а не з ключовим словом. Кар&amp;rsquo;єрний робочий простір постачається за feature flag і ще не випущений повністю; сторона найму вже працює.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Вакансію можна зіставити із задокументованою кваліфікацією, а не з назвою посади, яку людина написала про себе сама, — і саме в цьому вся різниця між дошкою оголошень і інструментом найму в цій галузі. Перевірка є вузьким місцем, і це навмисно: черга ручної перевірки не масштабується так, як масштабувалася б автоматична, а автоматична підтверджувала б кваліфікацію тим, кому її підтверджувати не можна.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Втримала всю компанію на одному хості з 512 МБ і одним ядром — git‑форж, вебсервер для семи доменів, Tor, два сервери альтернативних протоколів, резервні копії та блокування вторгнень — розглядаючи 464 МБ доступної пам&#39;яті як зобов&#39;язальне архітектурне обмеження.</title>
    <id>https://software.engineer.company/uk/portfolio/ran-the-whole-company-on-one-512mb-host-109/</id>
    <link href="https://software.engineer.company/uk/portfolio/ran-the-whole-company-on-one-512mb-host-109/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Linux та сервери" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура платформи" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Infrastructure as Code" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <category term="Хмарна інфраструктура та міграція" scheme="https://software.engineer.company/uk/services/" />
    <summary>Уся компанія працює на машині, що коштує на місяць менше за обід, і задум кращий саме завдяки цій дисципліні, а не просто дешевший.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Робочий хост компанії — це одноядерний хмарний примірник із 512 МБ пам&amp;rsquo;яті та 10 ГБ диска, з яких придатними до вжитку є близько 464 МБ. Усе, що бізнес виконує публічно, стоїть на ньому: вебсервер, що термінує TLS для семи доменів, git‑форджа, onion‑служба Tor, сервер Gemini, сервер Gopher, зашифровані резервні копії та блокування вторгнень. Звична реакція на цей перелік — придбати більшу машину.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Обмеження мало розглядатися як архітектурний вхідний параметр, а не як проблема, на яку витрачають гроші, бо чесне питання полягало не в тому, чи спрацювала б більша машина, а в тому, чи потрібна вона задуму.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Пам&amp;rsquo;ять стала аргументом, що вирішував суперечки. Немає ані агента моніторингу, ані конвеєра метрик, ані панелі — звітність є витягуванням, сім команд, що читають хост і формують Markdown, нічого не змінюючи й запускаючись лише на прохання. Наглядачем є systemd, а не другий менеджер процесів, накладений поверх нього, а контейнерна площина — це модулі Quadlet під тим самим наглядачем, а не демон із власним. Платформи з вебпанелями відкинуто ще на етапі задуму з тієї самої причини. Коли постало питання, чи витримає хост onion‑службу, відповідь надійшла з доби вимірюваних зразків, а не з думки: доступна пам&amp;rsquo;ять ніколи не опускалася нижче приблизно 310 МБ із 464, підкачування трималося на 2,6 відсотка, а процесор був вільним на 99,7 відсотка.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Уся компанія працює на машині, що коштує на місяць менше за обід, і задум кращий саме завдяки цій дисципліні, а не просто дешевший. Коштувало це запасу для будь‑чого недбалого — пошти навмисно немає на цій машині взагалі — її написано як риштування для встановлення, що чекає на власний хост, бо поштовий сервер потребує запасу, який ця машина вже витратила, і це записано, а не виявлено згодом.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Розгорнула власний git‑форж компанії на Soft Serve, приватний за замовчуванням і без вебпанелі, з портом SSH, прив&#39;язаним до loopback за хостом‑переходом, і зробила посадкову сторінку перед ним артефактом збірки основного сайту, а не копією, яку тримають руками.</title>
    <id>https://software.engineer.company/uk/portfolio/deployed-the-companys-own-git-forge-121/</id>
    <link href="https://software.engineer.company/uk/portfolio/deployed-the-companys-own-git-forge-121/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Linux та сервери" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Infrastructure as Code" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <summary>Компанія тримає власний код на власному обладнанні, а сторінка перед ним успадковує кожну перевірку, яку проходить головний сайт, замість того щоб відходити…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Початковий код компанії жив на сторонній хостинговій службі, що є розумним місцем для нього і поганим для бізнесу, чий аргумент перед клієнтами полягає в тому, що він не передає їхніх даних посередникам. Натомість тримати форджу означає тримати форджу: автентифікація, контроль доступу, сховище, резервні копії та публічне обличчя для всього цього.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Канонічний git‑сервер треба було підняти на наявному хості, з якнайменшою поверхнею атаки й без вебпанелі адміністрування, і поставити перед ним посадкову сторінку, що не гниє.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Форджа — це єдиний двійковий файл під наглядом операційної системи, встановлений із пакункового репозиторію постачальника, свідомо обраний за те, що він передусім працює через SSH і не має адміністративного вебінтерфейсу: що менше інтерфейсу, то менше треба захищати. Він приватний усталено: анонімний доступ відхиляється, доступ без ключа відхиляється, і кожен оголошений репозиторій позначено як приватний, а не покладено на невідомість. Його слухач SSH прив&amp;rsquo;язується лише до інтерфейсу зворотної петлі на порту 23231 і досяжний ззовні через хост‑перехід, тож оголошена поверхня брандмауера не зростає. Мультиплексор протоколів, що поставив би HTTPS і git‑SSH на один публічний порт, оглядаючи перші байти з&amp;rsquo;єднання, написано й готово за головним вимикачем, і цей вимикач вимкнено: багатокористувацький git через публічний порт поки не потрібен, а слухач, яким ніхто не користується, є поверхнею. Посадкова сторінка перед ним була цікавішою задачею. Вона була рукотворною копією оформлення головного сайту у власному репозиторії, і кожна знайдена між ними відмінність виявилася випадковістю, а не рішенням: шкала розмірів, що подавала словесний знак приблизно на дев&amp;rsquo;ять відсотків завеликим, оголошення шрифту, що зводило дві насиченості до однієї на будь‑якій машині зі встановленою гарнітурою, оздоби, приховані нижче певної ширини, тож відсутні на кожному телефоні, насиченість, використана без постаченого для неї шрифту, і жодного головного орієнтира чи заголовка верхнього рівня на жодній сторінці. П&amp;rsquo;ять із п&amp;rsquo;яти, і жодної видимої на знімку екрана. Копію видалено; посадкову сторінку тепер будують власні шаблони головного сайту й доставляють як артефакт.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Компанія тримає власний код на власному обладнанні, а сторінка перед ним успадковує кожну перевірку, яку проходить головний сайт, замість того щоб відходити від нього так, як здатне побачити лише вимірювання. Розходження досі доступне, і тепер його треба записати.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала багатомовний статичний сайт на Hugo зі 108 файлів шаблонів, з яких 53 партіали, що публікує кожну сторінку у чотирьох представленнях з одного дерева контенту трьома мовами, і ще раз під сімома сфокусованими субдоменами, зібраними з того самого дерева.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-multilingual-static-site-in-hugo-126/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-multilingual-static-site-in-hugo-126/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сайт віддає три мови та чотири подання з одного дерева, не має бекенду для атаки й нічого для оплати, а той єдиний шматок JavaScript у ньому тримається…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Компанії потрібен був публічний сайт, що працює трьома мовами, доводить спроможність, а не заявляє про неї, нічого не коштує в експлуатації й нікому не передає своїх відвідувачів. Більшість із цього — звичайні вимоги. Разом вони відкидають майже кожну систему керування вмістом, бо бекенд часу виконання — це те, що треба захищати, латати, оплачувати й пояснювати на сторінці приватності.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Сайт мав генеруватися цілком під час збирання і все ж поводитися як сучасний — із пошуком, встановлюваний, із стрічками, придатний до друку й читний екранним читачем кожною мовою, якою він виходить.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Це статичний сайт: 108 файлів шаблонів, з яких 53 є частковими шаблонами і 18 — шорткодами, три мови, жодного бекенду часу виконання й один власний скрипт, наданий як обмежений виняток для фільтра портфоліо, чий кожен елемент керування прихований, доки скрипт не запуститься. Спроможність додається під час збирання, а не в браузері, і це продуктове рішення, записане саме як рішення. Кожну сторінку публікують у чотирьох поданнях з одного дерева вмісту — HTML, двійник у Markdown, документ Gemini та пункт меню Gopher, — а головна сторінка додає до цього три стрічки та маніфест встановлюваного застосунку. Таксономій навмисно дві, а не одна, і ця відмінність є несучою: категорія є тематичною позначкою на роботі, послуга є тим, що компанія продає, і злиття їх зробило б каталог переліком навичок замість переліку пропозицій. Те саме дерево потім збирають ще сім разів, по одному на кожен сфокусований субдомен, скеровуючи генератор на інший каталог вмісту, а не відгалужуючи будь‑що.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сайт віддає три мови та чотири подання з одного дерева, не має бекенду для атаки й нічого для оплати, а той єдиний шматок JavaScript у ньому тримається контракту, який примусово застосовує лінтер. Ціна в тому, що все інтерактивне має розв&amp;rsquo;язуватися під час збирання або ніяк, і це відкинуло кілька речей, що були б легкими із сервером, і є причиною, чому пошуковий індекс оцінили та відклали, а не випустили.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Скоротила керовані браузером ворота якості сайту з 1 636 секунд до 615, плануючи їхні перевірки від найдовшої через пул воркерів, обмежений чотирма смугами, вимірявши, що абеткова черга коштувала 320 секунд проти 224.</title>
    <id>https://software.engineer.company/uk/portfolio/cut-the-visual-quality-gate-to-ten-minutes-128/</id>
    <link href="https://software.engineer.company/uk/portfolio/cut-the-visual-quality-gate-to-ten-minutes-128/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Перевірка пішла з 1 636 секунд на 615, тоді як самі перевірки стали ширшими, а не тоншими — послідовна вартість зросла, а час за годинником упав.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Одинадцять перевірок сайту керують браузером без вікна: розкладка за кожної форми вікна, яку малює дизайн, шкала розмірів, розширення перекладеного тексту, контраст, правила доступності, примусові кольори, розміри маскота, рух, друк у шести комбінаціях паперу, помилки консолі та візуальна регресія. Виконувані по одній, вони брали 1 636 секунд, трохи більш ніж двадцять сім хвилин. Перевірка, що триває двадцять сім хвилин, — це перевірка, яку пропускають, а пропущену перевірку не відрізнити від пройденої.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Час за годинником мав опуститися настільки, щоб їх запуск був усталеним варіантом, а не рішенням, і жодну з них при цьому не можна було послабити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Робота почалася з вимірювання. Кожну перевірку заміряно окремо на дванадцятиядерній машині: розкладка на 405 секундах, шрифт на 301, переклад на 282, контраст на 189, доступність на 178 і далі вниз аж до сімнадцяти. Відповідь сформували два висновки. Виконувати всі одразу було повільніше, ніж по чотири за раз, — 265 секунд проти 224, — бо кожна перевірка сама є браузером, що виконує паралельну роботу, і надмірне навантаження машини коштує більше, ніж виграє паралельність. А впорядкування за найдовшим часом обробки спершу перемогло абеткове майже на третину, 224 секунди проти 320, і це класичний результат теорії розкладів, який виявляється тут тому, що перевірки різняться у вартості в двадцять разів. Тож виконавцем є обмежений пул робітників, розмір якого береться з кількості ядер із підлогою в два та стелею в чотири, і який годують найдовшим спершу. Поряд із цим перевірки радше розширили, ніж звузили: вони тепер спільно використовують одну таблицю з двадцяти двох форм вікна, виведену з кожного медіазапиту, який насправді містить таблиця стилів, і це саме лише підняло перевірку розкладки з 95 секунд до 405.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Перевірка пішла з 1 636 секунд на 615, тоді як самі перевірки стали ширшими, а не тоншими — послідовна вартість зросла, а час за годинником упав. Вимірювання є тією частиною, яку варто зберегти: два розумні на слух вибори, виконувати все одразу й виконувати в порядку написання, кожен виявився вимірювано гіршим за альтернативу.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Замінила 27 відтворених розмірів шрифту, чиї найближчі сусіди різнилися на 0,6%, шестикроковою шкалою Major Third і написала лінтер, який валить двадцять восьмий.</title>
    <id>https://software.engineer.company/uk/portfolio/replaced-27-font-sizes-with-a-six-step-scale-129/</id>
    <link href="https://software.engineer.company/uk/portfolio/replaced-27-font-sizes-with-a-six-step-scale-129/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <summary>Шість розмірів там, де було двадцять сім, з оголошеним співвідношенням, оголошеною мірою та перевіркою, що відхиляє наступне незаплановане значення.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Вимірювання поданого тексту сайту виявило двадцять сім різних розмірів шрифту в ужитку. Кілька з них розділяв менш ніж один відсоток — п&amp;rsquo;ять значень між 0,8 і 0,85 від розміру основного тексту були живими одночасно, а це різниця, якої жоден читач не здатен відчути і до якої кожен наступний редактор додасть свою. Два заголовки таблиця стилів не розмічала за розміром узагалі, і вони провалювалися до власних усталених значень браузера, у співвідношення 1,33, що не відповідало нічому іншому на сторінці.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Розміри мали стати шкалою з оголошеним співвідношенням, і щось мало завадити появі двадцять восьмого.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Шкалою є велика терція зі співвідношенням 1,25, шість іменованих щаблів від дрібного шрифту до плакатного, кожен із яких є токеном, а не значенням. Заголовки явно накладено на щаблі замість успадкування того, що думає браузер, і саме це виправило ті два, що не мали власного розміру. Підлогу встановлено лише для найнижчого щабля, тож дрібний шрифт лишається читним на телефоні без прив&amp;rsquo;язування всієї шкали. Логотипи звільнено за іменем, а не випадково. Лінтер є тією частиною, що тримає це разом: він подає сайт і валить збирання на двадцять восьмому різному розмірі. Він уже двічі виправдав своє місце — спіймав заголовок, що прибув на 1,17 від розміру основного тексту, а це не щабель нічого, і назвав співвідношення в повідомленні про відмову; і спіймав вбудований код на 0,9, а це саме той різновид значення, заради запобігання якому шкала й існує. Поряд зі шкалою пішла міра приблизно у сімдесят два символи, що замінила успадковану фіксовану ширину, яка давала дев&amp;rsquo;яносто один символ на сторінці відгуку і сто десять на сторінці контактів.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Шість розмірів там, де було двадцять сім, з оголошеним співвідношенням, оголошеною мірою та перевіркою, що відхиляє наступне незаплановане значення. Обмеження реальне й подеколи незручне: дизайн, що хоче розмір між двома щаблями, мусить перейти на щабель або доводити потребу змінити шкалу, і цю суперечку вже не раз вели й програвали.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Довела WCAG 2.2 рівня AA на 32 представницьких сторінках — по одній на шаблон на мову — в обох колірних темах, плюс два критерії AAA, із задокументованим записом відповідності та перевіркою, що захищає кожне твердження.</title>
    <id>https://software.engineer.company/uk/portfolio/took-wcag-2-2-level-aa-across-the-whole-site-130/</id>
    <link href="https://software.engineer.company/uk/portfolio/took-wcag-2-2-level-aa-across-the-whole-site-130/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Відповідність заявлено на рівні AA трьома мовами й у двох темах, з двома критеріями AAA понад це та одним, названим як виняток, і за кожною заявою стоїть…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Консультація, що продає інженерну розсудливість і випускає недоступний вебсайт, має проблему з довірою ще до того, як має проблему з доступністю. Сайт до того ж має незвично широку поверхню для цього: три мови, дві колірні теми, повну таблицю стилів для друку, палітру з темною темою як основною, мальовані від руки примітки та ілюстрованого персонажа — і кожне з цього є способом провалити критерій в одній конфігурації, проходячи його в іншій.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Сайт мав відповідати WCAG 2.2 на рівні AA на кожній сторінці, кожною мовою та в обох темах, і цю відповідність мали захищати перевірки, а не заява в документі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Запис відповідності документує кожен критерій в обсязі, і кожен рядок називає, що його задовольняє і що це перевіряє. Два критерії рівня AAA взято понад ціль — візуальне подання цілком і вигляд фокуса, який радше пропонують, ніж заявляють. Автоматизація запускає рушій правил доступності з увімкненими правилами найкращих практик, а не лише з тими, що стосуються відповідності, а це різниця в тридцять правил, і вона важила одразу: одне з додаткових правил провалилося тієї миті, коли його ввімкнули, бо знак бренду стояв поза всіма орієнтирами на кожній внутрішній сторінці. Друга, повільніша перевірка проганяє тридцять дві представницькі сторінки у двох колірних схемах і двох ширинах, і те, що вона стверджує, є незвичним: фокус доводиться в пікселях, а не в документі, справжнім натисканням клавіші табуляції та порівнянням знімків екрана, бо однакові пікселі означають, що користувач не може сказати, де фокус, хай би що казала розмітка. Вона також обходить усю сторінку в пошуках клавіатурної пастки, застосовує зазначені перевизначення міжлітерних і міжслівних відступів, подвоює кореневий розмір шрифту та вимірює довжину рядка, вирівнювання, центрування та відступи між абзацами.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Відповідність заявлено на рівні AA трьома мовами й у двох темах, з двома критеріями AAA понад це та одним, названим як виняток, і за кожною заявою стоїть перевірка. Найважчою була контрастність над фотографією, яку автоматичний механізм правил позначає як таку, що її не оцінити, і яку сайт захищав аргументом, а не числом: справжні показники — 49 із 64 пар сторінки й теми нижче AA. Причиною виявилися дві поверхні, якими дизайн ніколи не володів, а перевірка, що їх знайшла, тепер є підлогою: кожна пара має витримувати AA над стіною, яку малює збірка, а пара, що не витримує, валить збірку. Те, що сайт каже на власній сторінці подяк, є чесною частиною: жоден автоматичний інструмент не знаходить більш ніж приблизно третину порушень WCAG, підписи, що з&amp;rsquo;являються під вказівником, не можна закрити клавішею, бо для цього потрібен скрипт, а сайт виконує лише один, і випробувань зі справжніми допоміжними технологіями не було — ці межі записано там, де читач їх побачить, а не вилучено із заяви.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Знайшла й виправила 11 дефектів доступності, які браузер звітував здоровими: вісім посилань підвалу, що лишалися в порядку табуляції за pointer‑events, шкалу прокрутки, яка обрізала колофон на трьох сторінках, і механізм правил, що виконував 70 зі своїх 105 правил.</title>
    <id>https://software.engineer.company/uk/portfolio/fixed-11-accessibility-defects-the-browser-called-healthy-131/</id>
    <link href="https://software.engineer.company/uk/portfolio/fixed-11-accessibility-defects-the-browser-called-healthy-131/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Одинадцять дефектів виправлено і, що корисніше, чотири правила, які їх переживуть: вартовий, що перевіряє одну вісь, захищає одну вісь; набір правил, що не…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт проходив свої автоматичні правила доступності. Він також мав одинадцять дефектів, яких ті правила не бачили, бо кожен із них був властивістю того, як сторінка подається, а не того, що казала розмітка, — саме той різновид, який валідатор звітує як справний і на який користувач клавіатури натрапляє за секунди.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Дефекти треба було знайти, виправити та описати як реєстр із правилом, яке породив кожен із них, щоб закривався клас дефектів, а не окремий випадок.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Вони поділилися на три групи. Розміри: ключове слово таблиці стилів, ужите так, ніби воно відносне, прив&amp;rsquo;язало цілу ділянку до шістнадцяти пікселів, тоді як основний текст сягав двадцяти двох; елемент нижнього індексу вжито у значенні «менший»; зменшення тексту подовжило рядок так, що заголовок сягнув дев&amp;rsquo;яноста шести символів; а виміряна стеля висоти була переросла саме тим перевизначенням відступів, підтримку якого сайт заявляє. Фокус і обрізання: вісім посилань підвалу лишалися в порядку табуляції за властивістю, що прибирає взаємодію вказівником і більш нічого; правило переповнення створило контейнер прокручування, якого ніхто не хотів; а анімація, керована прокручуванням, яка просто неактивна на сторінці, надто короткій для прокручування, назавжди обрізала підвал на трьох сторінках. І два дефекти в самих вартових, які варто назвати окремо, — кожна форма вікна, яку відкривала перевірка розкладки, мала дев&amp;rsquo;ятсот пікселів заввишки, тож телефон у альбомній орієнтації на 852 на 393 давав сім пікселів між двома елементами, і жодна перевірка туди ніколи не дивилася; а рушій правил виконував сімдесят зі своїх ста п&amp;rsquo;яти правил, тож правила, яке спіймало б відсутній орієнтир, у наборі не було.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Одинадцять дефектів виправлено і, що корисніше, чотири правила, які їх переживуть: вартовий, що перевіряє одну вісь, захищає одну вісь; набір правил, що не містить правила, не може його примусово застосувати; висота є виміром, тож перевіряйте її; і доводьте видимість у пікселях, а не в документі. Коли перевірку розкладки належно відкрили заново, вона провалилася сто двадцять вісім разів трьома мовами, зокрема на вікні завбільшки з телефон, де завершальний рядок головного блоку сидів на двадцять один піксель нижче згину.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Згенерувала 495 сторінок досягнень трьома мовами з експорту SQLite лише для читання, де адресу сторінки авторовано як дані, тож виправлення речення більше не пересувало сторінку й не ламало посилання.</title>
    <id>https://software.engineer.company/uk/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/</id>
    <link href="https://software.engineer.company/uk/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Пайплайни даних (ETL/ELT)" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка пайплайнів даних (ETL/ELT)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Чотириста дев&#39;яносто п&#39;ять сторінок генерується з одного джерела, виправлення твердження нічого не коштує, а адреси, які цей сайт колись публікував, і далі…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Вміст портфоліо компанії створюється в окремій базі даних — тій самій, що виробляє CV, — і вебсайт має публікувати його як сторінки, трьома мовами, не даючи двом копіям розійтися. Наївний підхід, писати сторінки вручну й тримати їх у злагоді, ламається на першому ж виправленні.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Вебсайт мав генерувати свій вміст із бази даних як вхідні дані збирання, з адресами сторінок, що переживають переписування речень на них.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Експортер читає базу даних лише для читання й пише по одній сторінці на досягнення на мову — 495 сторінок — плюс дані таксономії та послуг, потрібні шаблонам. Він використовує лише стандартну бібліотеку, тож збирання сайту не залежить від середовища генератора, а закомічений вивід означає, що сайт збирається самостійно. Найбільш наслідкове рішення в ньому стосується адрес. Раніше сайт виводив URL сторінки з перших слів її англійського твердження, тож виправлення речення мовчки переносило сторінку й ламало кожне посилання на неї — сайт, чиїм аргументом на власну користь є те, що він виправляє речі, штрафував себе мертвим посиланням щоразу, коли це робив. Адресу тепер створюють як дані: по одному рядку на адресу на досягнення, перша є поточною, а кожна наступна є відставленою адресою, яку сайт видає як перенаправлення. З тієї самої роботи записано ще дві пастки. Порівняння періоду з текстовим стовпчиком мовчки збіглося з усіма тридцятьма двома рядками через те, як база даних призначає спорідненість типів у порівнянні. І перелік мов тепер є єдиною віссю, з якої виводять і цикл запису, і файли даних, і запити, тож додати четверту мову — це один запис у відображенні, а не пошук.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Чотириста дев&amp;rsquo;яносто п&amp;rsquo;ять сторінок генерується з одного джерела, виправлення твердження нічого не коштує, а адреси, які цей сайт колись публікував, і далі відповідають. Експортер також володіє рівно одним рішенням про подання — тим, як послуги групуються в тематичні розділи, — і це навмисно: усе інше, що він пише, належить базі даних, а заголовок групи без якоїсь мови валить експорт, а не подає англійську поверх перекладеного вмісту.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Закрила систему кольорів на 28 задокументованих кольорах із лінтером, який валить значення, намальоване але незадокументоване, задокументоване але ненамальоване, хибно виміряне, переписане як літерал або в межах перцептивної відстані 0,02 від уже наявного.</title>
    <id>https://software.engineer.company/uk/portfolio/closed-the-colour-system-at-28-colours-133/</id>
    <link href="https://software.engineer.company/uk/portfolio/closed-the-colour-system-at-28-colours-133/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <summary>Палітра є замкненим виміряним набором, що не може тихо зростати, а два майже однакові написання, які до цього спонукали, зникли.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Колір на сайті з темною темою за усталеним вибором, світлою темою, таблицею стилів для друку, режимом примусових кольорів та ілюстрованим брендом сам собою не лишається малим набором. Він уже почав розходитися так, як завжди: два написання того самого кольору стояли досить близько, щоб ніхто не міг їх розрізнити, значення були перевведені як літерали поруч із токенами, що їх визначали, а задокументовані кольори не фарбували нічого.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Палітра мала стати замкненим набором із оголошеним порогом розрізненності, і щось мало примусово тримати цю замкненість.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Двадцять вісім кольорів, кожен задокументований із коефіцієнтом контрасту, який він показує на поверхні, де з&amp;rsquo;являється, та одинадцять брендових значень, оголошених один раз як токени. Поріг є числовим, а не редакційним: два кольори, ближчі за перцептивну відстань 0,02 в однорідному колірному просторі, є одним кольором із двома написаннями. Лінтер валить збирання п&amp;rsquo;ятьма різними способами — значення пофарбоване, але незадокументоване; задокументоване, але непофарбоване; записане з хибним коефіцієнтом; у межах порога від того, що вже є; або брендове значення, переписане як літерал. Він одразу знайшов два: колір теми, що існував у двох написаннях на відстані 0,018, і колір тла, що заміняв стіну, від якої стояв на 0,021. Прозорість використовує відносний колірний синтаксис, а не функцію змішування, саме тому, що вартовий не бачить крізь суміш, а палітрний вартовий, якого можна обійти, не є вартовим. Правило, що йде з цим, коротке: змінюйте токен, а не правило, додавайте колір лише тоді, коли жоден не пасує, і ніколи не знижуйте задокументований коефіцієнт, щоб дизайн запрацював.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Палітра є замкненим виміряним набором, що не може тихо зростати, а два майже однакові написання, які до цього спонукали, зникли. Це обмеження, що подеколи каже ні: дизайн, який хоче трохи інший синій, мусить узяти той, що існує, або обґрунтувати двадцять дев&amp;rsquo;ятий колір, і це обґрунтування має містити коефіцієнт.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Виявила, що світлій темі бракувало повносторінкового шару накладання від самого дня її написання, стверджуючи, що обидві теми малюють кожну шарувату поверхню однаковою кількістю шарів.</title>
    <id>https://software.engineer.company/uk/portfolio/found-the-light-theme-missing-an-overlay-layer-134/</id>
    <link href="https://software.engineer.company/uk/portfolio/found-the-light-theme-missing-an-overlay-layer-134/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <summary>Шар, відсутній в одній темі, тепер валить коміт, а той, що був відсутнім від дня написання, пофарбовано.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт постачає дві колірні теми. Темна є усталеною і на неї дивляться постійно; світла є перевизначенням, що з&amp;rsquo;являється лише за системною вподобою, а це означає, що її бачать значно рідше і ніхто з тих, хто її перевіряє. Паритет тем є класом дефектів, у якому поверхню будують один раз і переказують один раз, а переказ тихо губить шар.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Паритетові потрібне було твердження, бо єдиною альтернативою є людина, яка пам&amp;rsquo;ятає перемкнути вподобу й подивитися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Перевірка мала й структурна: для кожної шаруватої поверхні порахувати шари, які фарбує кожна тема, і завалити, коли числа різняться. Вона не порівнює вигляд — теми й мають виглядати по‑різному, — вона порівнює склад, а це та річ, що має бути однаковою. Вона знайшла дефект на першому ж прогоні. Повносторінкова обкладинка сайту має три шари в темній темі, візерунок граней над затінювачем над стіною, а світла тема переказала це двома. Накладення граней було відсутнім у світлій темі від дня її написання, і ніщо про це не сказало, бо сторінка без одного з трьох шарів тла має вигляд дизайнерського рішення, а не вади. Виправленням було одне правило; опис, зроблений згодом, зафіксував, чого накладення коштує в контрасті, тож додавання виміряно, а не вважається безкоштовним.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Шар, відсутній в одній темі, тепер валить коміт, а той, що був відсутнім від дня написання, пофарбовано. Це і є форма дефекту, на яку націлено весь підхід із перевірками: нічого не було зламано, нічого не давало помилки, сторінка подавалася правильно, і вона була хибною місяцями.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Зробила зменшений рух чесним, знайшовши одинадцять селекторів, які досі анімувалися під цією настройкою, бо універсальне правило transition‑none програє за специфічністю будь‑якому правилу з класом.</title>
    <id>https://software.engineer.company/uk/portfolio/made-reduced-motion-honest-135/</id>
    <link href="https://software.engineer.company/uk/portfolio/made-reduced-motion-honest-135/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Уподобу шанують насправді, а не за наміром, і одинадцять живих анімацій, які суцільне правило нібито покривало, покрито справді.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт шанував уподобу зменшеного руху одним правилом, що вимикало кожен перехід. Воно мало вигляд завершеного, воно проходить лінтер чисто, і за емульованої вподоби зменшеного руху одинадцять селекторів усе одно анімувалися.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Уподобу треба було шанувати насправді, а причина, чому очевидне правило не спрацювало, мала стати тим, чого наступна людина не зможе повторити.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Причиною є специфічність. Універсальне правило набирає найнижчий бал у каскаді й програє будь‑якому правилу з класом, тож суцільне вимкнення переходів програє кожній продуманій анімації на сторінці — а це і є кожна анімація, яку варто вимикати. Виправлення було структурним, а не латкою: усе, що рухається, тепер живе в одній пізній частині таблиці стилів, а лінтер валить перехідне перетворення будь‑де інде. Розрізнення, яке проводить правило, є навмисним і вужчим за очевидне: зменшуйте рух, а не колір. Згасання кольору не є рухом, і його вимкнення робить інтерфейси на відчуття зламаними для людей, які цього не просили, тож перехід, що перелічує колірні властивості, проходить, а перехід на русі — ні. Рух також зобов&amp;rsquo;язаний виражатися як перехід, а не як анімація за ключовими кадрами, бо перший тривіально скасовується, а друга — ні. З тієї самої роботи вийшли дві суміжні пастки, записані з вимірюваннями: оздоба меню проходила тридцять один градус із шістдесятиградусного повороту, перш ніж стати наполовину видимою, і оскільки форма періодична, півповорот має однаковий вигляд за третину вартості; і п&amp;rsquo;ять різних властивостей кожна робить елемент вмісним блоком для всього, спозиційованого відносно вікна перегляду, що мовчки зменшило шар закривання до частки екрана.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Уподобу шанують насправді, а не за наміром, і одинадцять живих анімацій, які суцільне правило нібито покривало, покрито справді. Загальний урок записано на початку того документа: правило, що програє за специфічністю, відмовляє мовчки, і кожен звіт називає це якось інакше.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала друкований стиль на 637 рядків проти чотирьох задокументованих поведінок рушія відтворення, зокрема вбудованих заголовків, які друкувалися білим по білому для будь‑якого читача, чий браузер надавав перевагу темному.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-637-line-print-stylesheet-136/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-637-line-print-stylesheet-136/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сайт друкується на невідомому папері в обох темах, а чотири види поведінки рушіїв записано разом із дефектом, який спричинив кожен.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Кейси сайту є тим артефактом, який хтось роздруковує й несе на зустріч. Це робить папір справжнім виходом, а не люб&amp;rsquo;язністю, а папір є іншим носієм, ніж вузький екран — розмір паперу читача невідомий, орієнтація читача невідома, а поведінка браузера під час друку різниться між рушіями так, як жодний екранний перегляд не покаже.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Сайт мав друкуватися правильно на невідомому папері, в обох колірних темах, без окремого документа, який довелося б підтримувати поруч із вебверсією.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Це одна таблиця стилів на 637 рядків з єдиним правилом сторінки й одним блоком друку. Правило сторінки задає поле й навмисно не задає розміру паперу, тож те, що читач обере в діалозі, проходить наскрізь, і все інше до цього пристосовується. Кореневий розмір шрифту закріплено в пунктах, тож кожне відносне вимірювання має фізичний якір, а одну міру приблизно у сімдесят два символи застосовано до чотирьох блоків верхнього рівня — і це аркуш перемагає дизайн, бо альбомна сторінка інакше розганяла б рядок приблизно до ста десяти символів. Чотири види поведінки рушіїв задокументовано як пастки, і кожен спричинив справжній дефект. Одиниці вікна перегляду розв&amp;rsquo;язуються в коробку сторінки в одному рушії й у вікно в іншому, тож сторінка, надрукована з широкого вікна, має третину кожного рядка обрізаною в другому. Елементи з фіксованим положенням малюються на кожному аркуші, тож декоративні прибрано, а два з них перепризначено на бланк і колофон. Палітра усталено бере білий текст, бо усталеною темою є темна, і це друкувало чотири підзаголовки розділів білим по білому — слова просто були відсутні. А сторінковий носій не може розділити гнучку чи сіткову коробку, що дало порожній перший аркуш на сторінці досягнення. Це покриває перевірка з шести частин, що випробовує шість комбінацій паперу й орієнтації, обидві вподоби колірної схеми та справжню кількість сторінок проти тієї, яку передбачає висота вмісту.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сайт друкується на невідомому папері в обох темах, а чотири види поведінки рушіїв записано разом із дефектом, який спричинив кожен. Відомі межі записано, а не приховано: немає ні номерів сторінок, ні колонтитулів, один рушій ігнорує контроль висячих рядків, а буквиці не є універсальними. Одного разу випадковий термінатор коментаря змусив лінтер CSS проковтнути ціле правило і двічі пройти чисто — помітила це лише перевірка друку.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Віддзеркалила весь сайт як 777 документів Gemini і 777 документів Gopher з того самого розгорнутого дерева, з нульовою зміною байтів у HTML.</title>
    <id>https://software.engineer.company/uk/portfolio/mirrored-the-site-to-gemini-and-gopher-137/</id>
    <link href="https://software.engineer.company/uk/portfolio/mirrored-the-site-to-gemini-and-gopher-137/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сайт читний чотирма протоколами з одного збирання, по 777 документів на кожен і з нульовою зміною HTML, а альтернативні подання коштують приблизно дванадцять…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт статичний, не має ні стеження, ні бекенду часу виконання, і його аргумент полягає в тому, що документові не потрібен мегабайт JavaScript, аби його прочитали. Цей аргумент легко висловити й важко продемонструвати. Два невеликі інтернет‑протоколи демонструють його безпосередньо, бо жоден із них узагалі не здатен нести скрипт.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Увесь сайт мав публікуватися через Gemini і Gopher із того самого вмісту, без другого дерева вмісту й без змін у HTML.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Обидва є форматами виводу того самого збирання, а не окремим конвеєром. Генераторові сайту надали власні типи носіїв і формати виводу, і кожна сторінка, розділ та термін таксономії дістали ще по два подання поруч зі своїм HTML і двійником у Markdown. Результатом є 777 документів Gemini і 777 меню Gopher, вироблені з того самого джерела, розгорнуті в те саме дерево й віддавані двома невеликими демонами на тому самому хості. Дві властивості зробили це вартим роботи, а не дивиною. Обидва формати позначено як неальтернативні подання, тож у HTML не змінилося нічого — жодного байта, і це виміряли, а не припустили. А формат Gopher не має способу вкласти посилання всередину речення, бо рядок меню є полями, розділеними табуляціями, тож прозу жорстко переносять на шістдесят восьмому стовпчику під час збирання; це обмеження вигострило письмо так, як HTML ніколи не вимагав. Поруч із ними стоїть onion‑дзеркало Tor, і це єдине публічне обличчя, яке платформа могла додати, не відкриваючи порту брандмауера, бо демон додзвонюється назовні, а всередину не дзвонить ніхто.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сайт читний чотирма протоколами з одного збирання, по 777 документів на кожен і з нульовою зміною HTML, а альтернативні подання коштують приблизно дванадцять відсотків від власної ваги HTML на диску. Лише один із чотирьох вимірюється щодо трафіку, і це зазначено у власному документі статистики платформи, а не тихо проігноровано.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Замінила 963 анонімні блоки структурованих даних, які переповідали компанію 1 671 раз, одним пов&#39;язаним графом із 16 типів, викарбуваним зі стабільних ідентифікаторів походження.</title>
    <id>https://software.engineer.company/uk/portfolio/replaced-963-structured-data-blocks-with-one-graph-138/</id>
    <link href="https://software.engineer.company/uk/portfolio/replaced-963-structured-data-blocks-with-one-graph-138/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бренд і маркетинг" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Один граф зі стабільною тотожністю замінює 963 анонімні переказування, і сторінки несуть менше, а не більше.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт видавав структуровані дані так, як це робить більшість сайтів: по блоку на сторінку, і кожен описував організацію заново з нуля. На весь сайт це дало 963 блоки, що переказували ту саму компанію 1 671 раз, анонімно — жодного стабільного ідентифікатора ніде, тож ніщо із тих, хто це споживає, не могло сказати, що організація на одній сторінці є організацією на іншій.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Структуровані дані мали стати одним графом зі стабільною тотожністю, а не купою блоків, що випадково містять ті самі слова.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Ідентифікатори тепер карбують із джерела сайту — один для організації, один для сайту, один для особи, — і кожен блок посилається на них, а не переказує їхній вміст. Ідентифікатори є спільними для джерела, а не окремими для кожної мови, бо компанія є тією самою компанією й данською. У грі шістнадцять типів, що охоплюють каталог послуг і його пропозиції, відгуки та роботу, яку вони описують, добірки та їхні навігаційні ланцюжки. Два рішення втримали вагу. Сторінки переліків публікують свої елементи лише за URL, а не вбудовують їх, і це виміряли: назвати їх на індексі портфоліо означало б 107 повних тверджень і зростання стиснутої сторінки на 52 відсотки. А перевірка, що це стереже, не просто підтверджує синтаксис — вона стверджує, що кожен блок розбирається, що кожен ідентифікатор розв&amp;rsquo;язується і що кожну URL‑адресу, яку називає граф, справді було зібрано, тож граф, що вказує на неіснуючу сторінку, валить перевірку.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Один граф зі стабільною тотожністю замінює 963 анонімні переказування, і сторінки несуть менше, а не більше. Вимірювання, з якого почалася робота, варто тримати в голові: сайт видавав той самий опис організації 1 671 раз, і ніщо не могло їх поєднати.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Скоротила пакунок стилів із 87 КБ до 31 КБ, вийнявши з нього шрифт у base64, і відкинула 756 КБ у 22 файлах, які публікувалися при кожному розгортанні й на які ніщо не посилалося.</title>
    <id>https://software.engineer.company/uk/portfolio/cut-the-stylesheet-bundle-from-87kb-to-31kb-139/</id>
    <link href="https://software.engineer.company/uk/portfolio/cut-the-stylesheet-bundle-from-87kb-to-31kb-139/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Пакет важить 31 КБ замість 87, 756 КБ мертвих ресурсів перестали розгортатися, і за кожним рішенням стоїть вимірювання — зокрема за тим, що пішло в інший бік,…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Пакет таблиць стилів сайту важив 87 КБ, а для документного сайту без фреймворку це більша частина ваги сторінки, витрачена ще до прибуття будь‑якого вмісту. Сайт до того ж публікував каталог піктограм за кожного розгортання, згенерований один раз і відтоді ні з чого не згаданий.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Вага мала впасти без зміни дизайну, і мала впасти з причини, на яку можна вказати, а не через загальне прибирання.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Спершу вимірювання. Дві третини найбільшої таблиці стилів були одним шрифтом, закодованим у base64, — приблизно 56 КБ тексту, що кодували приблизно 42 КБ шрифту, — вбудованим заради виграшу в першому промальовуванні, який попередньо завантажений зовнішній файл дає й так, і оплачуваним на кожній сторінці незалежно від того, чи потрібна була та вага. Його вилучення забрало цей файл з 84 КБ до 28, а весь пакет з 87 до 31. Три насиченості шрифту натомість попередньо завантажуються, і третя приєдналася до переліку лише тоді, коли польові дані показали, що вона закриває найдовший критичний ланцюжок, а не тому, що три звучить завершено. Окремо перевірка того, що розгортання насправді публікувало, виявила двадцять одну згенеровану піктограму та дублікат файлу налаштувань, 756 КБ, що вивантажувалися щоразу й не згадувалися нізвідки; а власний файл піктограм сайту впав із 145 КБ до 15. Сучасний формат зображень оцінили для знака бренду, виміряли й відхилили — він вийшов більшим, а механізм вибору бере за порядком, а не за розміром, тож сучасний браузер брав би скрізь важчий файл. Дві перевірки тепер тримають межу: жодну світлину не можна показувати ширшою за половину її вихідних пікселів, і кожну ілюстрацію треба публікувати в розмірі, який підтримують її власні пікселі і за звичайної, і за високої щільності.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Пакет важить 31 КБ замість 87, 756 КБ мертвих ресурсів перестали розгортатися, і за кожним рішенням стоїть вимірювання — зокрема за тим, що пішло в інший бік, і це корисніший запис із двох.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Виправила мапу сайту, де 172 з 176 URL мали одну позначку часу зміни, взявши дату з історії git після встановлення, що експорт переписує кожен файл при кожному запуску.</title>
    <id>https://software.engineer.company/uk/portfolio/fixed-a-sitemap-with-one-shared-timestamp-140/</id>
    <link href="https://software.engineer.company/uk/portfolio/fixed-a-sitemap-with-one-shared-timestamp-140/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бренд і маркетинг" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Повторна синхронізація після місяця редагування вмісту тепер торкається восьми файлів зі 186 замість усіх, і мапа сайту каже щось правдиве.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Мапа сайту казала пошуковим системам, що 172 з його 176 сторінок востаннє змінилися тієї самої миті. Це не тонка неточність — дата зміни є обіцянкою повзунові, що вміст сторінки змінився, і сайт, який дає цю обіцянку 172 рази одночасно, або каже правду про повне переписування, або не каже нікому нічого корисного.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Дати мали описувати вміст, а не файл, не вигадуючи точності, якої репозиторій не має.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Причиною було те, що дата бралася з часу зміни файлу, а експорт вмісту переписує кожен файл за кожного прогону, тож одна синхронізація штампувала весь корпус. Виправлення переносить джерело до історії версій, із ланцюжком запасних варіантів, що пробує спершу явне поле, потім історію комітів, потім файл. Пастка в цьому виправленні варта запису: буквальна назва поля має з&amp;rsquo;явитися в переліку, інакше генератор ніколи його не прочитає, тож налаштування, що на вигляд віддає перевагу авторській даті, але пропускає назву, мовчки ігнорує кожну авторську дату. З тієї самої роботи вийшли ще два рішення про дати. База даних тепер несе, коли кожен запис було написано й востаннє переглянуто, і це навмисно тримають окремо від того, коли відбулася сама робота, — вони віддалені на роки, і злиття їх датувало б сторінку, написану цього року, десятиліттям тому. А рядки в тому файлі є необов&amp;rsquo;язковими, і нічого не виводиться, бо власна історія репозиторію починається пізніше за вміст: відсутня дата лишає поле порожнім, а не фіксує міграцію, за принципом, що точне хибне число гірше за відсутнє, бо вірять саме хибному.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Повторна синхронізація після місяця редагування вмісту тепер торкається восьми файлів зі 186 замість усіх, і мапа сайту каже щось правдиве. Загальне правило потрапило до документа з метаданими поруч, бо та сама пастка стосується кожного поля, що має ланцюжок запасних варіантів.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Підвела 10 242 рядки JavaScript воріт якості під форматувальник і лінтер, встановивши, що це найбільший обсяг коду в репозиторії й єдиний, якого ніщо не читало, виправила 13 знахідок і не придушила жодної.</title>
    <id>https://software.engineer.company/uk/portfolio/brought-the-quality-gate-code-under-a-linter-143/</id>
    <link href="https://software.engineer.company/uk/portfolio/brought-the-quality-gate-code-under-a-linter-143/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Найбільший і найбільш несучий код у репозиторії тепер відформатовано, перевірено лінтером і перевірячем типів, із тринадцятьма виправленими висновками й нулем…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Перевірка якості сайту — це тридцять два скрипти загальним обсягом 10 242 рядки JavaScript. Це був із великим відривом найбільший масив коду в репозиторії, і це був єдиний масив коду, якого ніщо не читало — ані форматувальник, ані лінтер, ані перевірка типів. Програми, що примусово застосовували кожне правило в проєкті, були єдиними програмами, на які не поширювалося жодне з них.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Перевіряльників треба було підвести під той стандарт, заради примусового застосування якого вони існують, і форматувальник треба було припасувати до них, а не навпаки.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Форматувальник ішов першим, і ширина відступу була цікавим рішенням. Усталеним значенням репозиторію є чотири пробіли; за чотирьох пробілів форматувальник переписав би 2 173 рядки найбільшого перевіряльника. Перевизначення на два пробіли для цих файлів звело це до 38 рядків справжнього розходження. Записаний із цим принцип полягає в тому, що форматувальник припасовують до коду, а не код до форматувальника — переформатування двох тисяч рядків заради вподобання знищує здатність читати історію файлу. Далі лінтер, що дав тринадцять справжніх висновків, усі виправлено й жодного не придушено. Перевіряльники на Python дістали те саме поводження через перевіряч типів, налаштований на середню суворість із тридцятьма окремими правилами суворого рівня, увімкненими понад це й обраними за вимірюванням: за цього налаштування дерево мовчить, і з тридцяти кандидатів двадцять дев&amp;rsquo;ять уже мовчали, а один спрацював — і його виправили, а не звільнили. Перевіряч типів знайшов два справжні дефекти, які лінтер пропустив чистими, обидва про форму значення, а не про його синтаксис.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Найбільший і найбільш несучий код у репозиторії тепер відформатовано, перевірено лінтером і перевірячем типів, із тринадцятьма виправленими висновками й нулем придушень. Причина, чому це важить більше, ніж підказує кількість рядків, зазначена в плані: дефект у таблиці стилів сайту виявляється як сторінка, що виглядає хибно, а дефект у перевіряльнику виявляється як перевірка, що проходить тоді, коли не мала б.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала на Python генератор CV, рекомендацій, портфоліо та супровідних листів на основі бази даних — 41 модуль, 10 580 рядків — що відтворює шість форматів виводу з одного джерела SQLite на 23 таблиці, зібраного ідемпотентним конвеєром із 19 кроків.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-database-driven-cv-and-portfolio-generator-144/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-database-driven-cv-and-portfolio-generator-144/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="SQL" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Проєктування та моделювання баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Шість форматів, три мови й п&#39;ять тем виходять з однієї бази даних, а виправлене речення виправляють один раз.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; CV, аркуш рекомендацій, портфоліо та супровідний лист — це ті самі факти, впорядковані чотирма способами, і тримати їх як чотири документи означає робити кожне виправлення чотири рази, а зрештою не робити. Три мови множать це на три. Режим відмови полягає не в тому, що документ хибний; він у тому, що два документи розходяться, і ніщо не каже, який із них поточний.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Одне джерело фактів мало виробляти кожен документ, кожною мовою, у кожному форматі, з упорядкуванням, яке вирішує код, а не той, хто останнім редагував файл.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Джерелом є база даних SQLite із двадцяти трьох таблиць — досягнення, посади, компанії, регіони, категорії, послуги, профілі, рекомендації, резюме, — зібрана конвеєром із дев&amp;rsquo;ятнадцяти кроків, що йде від порожнього файлу до повної бази даних однією командою. Кроки впорядковано, і кожен написано так, щоб його було безпечно повторювати, тож конвеєр можна виконати проти наявної бази даних, не дублюючи жодного рядка. Сорок один модуль Python загальним обсягом 10 580 рядків подають із неї шість вихідних форматів: HTML, PDF у двох варіантах, звичайний текст, Markdown і JSON, через шість шаблонів Jinja і вісім таблиць стилів. Залежності часу виконання втримано рівно на двох, шаблонний рушій і рендерер PDF, з тим аргументом, що генератор документів, який не вдасться встановити за п&amp;rsquo;ять років, нічого не зберіг. Націлювання є повноцінним поняттям, а не ручним редагуванням: профіль обирає, які досягнення з&amp;rsquo;являються і в якому порядку, тож документ, спрямований на один різновид читача, є запитом, а не копією.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Шість форматів, три мови й п&amp;rsquo;ять тем виходять з однієї бази даних, а виправлене речення виправляють один раз. Ціна в тому, що система тепер є єдиним способом виробити документ — більше немає файлу, який можна поспіхом відкрити й відредагувати, а додати мову означає додати її скрізь, перш ніж узагалі щось збереться.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Втримала генератор на 981 тестовому випадку із порогом покриття гілок 92% і попередженнями як помилками та ствердила ідемпотентність, запустивши весь конвеєр збірки двічі з порожнього файлу й вимагаючи, щоб другий прохід нічого не змінив.</title>
    <id>https://software.engineer.company/uk/portfolio/held-the-generator-to-964-tests-and-a-coverage-floor-145/</id>
    <link href="https://software.engineer.company/uk/portfolio/held-the-generator-to-964-tests-and-a-coverage-floor-145/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бази даних" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Конвеєр можна повторно виконати проти живої бази даних без страху, і саме це взагалі уможливлює поступову роботу з вмістом.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Генератор, що збирає базу даних з нуля, має особливий різновид вади: він працює першого разу й псує другого. Кроки, що вставляють без перевірки, кроки, що залежать від порядку виводу попереднього кроку, кроки, безпечні поодинці й не разом. Нічого з цього не виявляється в тесті, що починає з нічого й виконується один раз.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Збирання треба було довести як повторюване, а не просто робоче, а набір тестів мав бути достатньо великим і суворим, щоб регресія не змогла тихо крізь нього пройти.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Тест ідемпотентності є прямолінійним і найкориснішим: зібрати всю базу даних із порожнього файлу, зробити знімок, виконати весь дев&amp;rsquo;ятнадцятикроковий конвеєр знову поверх результату й вимагати, щоб другий прохід нічого не змінив. Кількості рядків, вміст та ідентифікатори мають збігатися. Довкола нього стоять 383 тестові функції — 981 випадок, коли параметризовані розгортаються, — у сорока п&amp;rsquo;яти файлах і 7 944 рядках, що охоплюють конвеєр, рендерери, завантажувачі вмісту, логіку націлювання та перевіряльників. Покриття гілок несе підлогу в дев&amp;rsquo;яносто два відсотки, примусово застосовану в збиранні, а не подану в підсумку, і набір наразі показує близько 95 відсотків, тож підлога має запас і не є декоративною. Попередження налаштовано як відмови, і саме це налаштування на практиці важить найбільше — сповіщення про застарілість, що друкується два роки, є сповіщенням, якого ніхто не читає, а прогін, що перетворює його на червоний тест, є тим прогоном, після якого його виправлять.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Конвеєр можна повторно виконати проти живої бази даних без страху, і саме це взагалі уможливлює поступову роботу з вмістом. Підлога є підлогою, а не ціллю, і варто сказати, що дев&amp;rsquo;яносто два відсотки покриття гілок усе одно лишають гілки, якими ніщо ніколи не проходило, — число обмежує ризик, а не усуває його, і два дефекти, знайдені в проєкті згодом, були в коді, який звіт про покриття показував як покритий.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Встановила відповідність PDF/UA‑1 на дев&#39;яти документах за 106 зі 106 правил і виявила, що архівний варіант валить одне правило зі 146 — майже‑успіх, який читається як успіх для будь‑кого, хто не запускає валідатор.</title>
    <id>https://software.engineer.company/uk/portfolio/established-pdf-ua-1-conformance-across-nine-documents-146/</id>
    <link href="https://software.engineer.company/uk/portfolio/established-pdf-ua-1-conformance-across-nine-documents-146/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Відповідність доступності доведено на повний бал, а архівну заяву висловлено чесно як майже влучання із названою конкретною прогалиною.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; PDF, що має правильний вигляд на екрані, не каже нічого про те, чи здатен його прочитати екранний читач, чи утворюють його заголовки структуру, чи оголошено його мову і чи відкриється він ще за двадцять років. Відповідність доступного PDF і архівного PDF є двома машинно перевірюваними стандартами, а документ, якого ніколи не проганяли через валідатор, є документом, що робить неперевірену заяву.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Згенеровані документи треба було зміряти проти обох стандартів, із результатом, записаним як число, а не як намір.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Дев&amp;rsquo;ять документів — CV у своїх варіантах, аркуш рекомендацій, портфоліо та супровідний лист, у різних мовах — прогнали через незалежний валідатор окремо для профілю доступності й архівного профілю. Профіль доступності проходить на 106 зі 106 правил, і це вимагало тегованої структури, оголошеної мови документа, альтернативного тексту на кожній недекоративній графіці, справжнього заголовка в метаданих і явного порядку читання замість того, який випадково дає розкладка. Архівний профіль дає цікавіший результат: він валить рівно одне правило зі 146. Це та форма результату, яку легко подати хибно. Сто сорок п&amp;rsquo;ять пройдених у підсумку читається як відповідність, і це не відповідність; це документ, який відхилить система, що застосовує стандарт. Правило, яке не проходить, записано разом із тим, що воно є і чому його не закрито, а не заокруглено геть.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Відповідність доступності доведено на повний бал, а архівну заяву висловлено чесно як майже влучання із названою конкретною прогалиною. Межа, про яку варто сказати прямо, полягає в тому, що обидва числа походять від одного валідатора; інша реалізація може не погодитися, а правило, що проходить, є лише свідченням того, що цьому перевіряльникові не було чого про нього сказати.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Обрала кожне правило, яке має лінтер Python, як помилку й опрацювала 1 815 знахідок до нуля, де кожен із небагатьох винятків несе письмову причину, а два з них підперті перевіркою, а не коментарем.</title>
    <id>https://software.engineer.company/uk/portfolio/enabled-every-python-linter-rule-as-an-error-147/</id>
    <link href="https://software.engineer.company/uk/portfolio/enabled-every-python-linter-rule-as-an-error-147/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="DevOps" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Лінтер працює на повну силу з нулем висновків, і кожне відхилення задокументовано в тому рядку, де його взято.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Більшість проєктів обирає зручну підмножину правил свого лінтера, і цю підмножину обирають ті правила, що мовчали того дня, коли його налаштовували. Це робить налаштування записом наявних звичок коду, а не стандартом, якого код дотримується, і кожне лишене вимкненим правило є класом дефектів, про який нікому ніколи не скажуть.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Усталений вибір треба було обернути — кожне правило, яке реалізує інструмент, увімкнене як помилка, — а отриманий доробок відпрацювати до нуля, а не виторгувати вниз, вимикаючи правила назад.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Вибір повного набору правил дав 1 815 висновків на першому прогоні. Їх опрацьовували за категоріями, а не за файлами, бо категорії про щось кажуть: невживані аргументи та затінені вбудовані імена є шумом, а категорія безпеки, категорія змінюваних усталених значень і категорія обробки винятків кожна вказувала на справжню поведінку. Справжні несумісності існують — форматувальник і лінтер можуть розходитися щодо того самого рядка, а кілька правил суперечать власним свідомим виборам проєкту, — і кожне з невеликої кількості звільнень несе письмову причину в тому місці, де звільнення береться, і каже, чого хотіло правило й чому цей код робить інакше. Два з них ідуть далі й підперті перевіркою, а не коментарем, тож звільнення не може тихо розширитися: правило вимкнено, а тест стверджує саме ту властивість, яку правило примусово застосувало б. Поряд працює перевірка типів у суворому режимі, а це окремий і жорсткіший стандарт, і саме вона спіймала дефекти, яких лінтер не бачив, бо вони про те, чим значення є, а не про те, як його записано.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Лінтер працює на повну силу з нулем висновків, і кожне відхилення задокументовано в тому рядку, де його взято. Ціна реальна й варта називання: найсуворіше налаштування дає висновки, на які щиро не варто зважати, і хтось має ухвалювати це рішення 1 815 разів, а не один раз.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Вбудувала кодувальник QR — Ріда‑Соломона над GF(256), фіксоване розташування модулів, вісім шаблонів маски — на 522 рядках, замість брати третю залежність часу виконання, і перевірила його, зчитавши готову матрицю незалежно написаним декодером.</title>
    <id>https://software.engineer.company/uk/portfolio/vendored-a-qr-encoder-in-522-lines-148/</id>
    <link href="https://software.engineer.company/uk/portfolio/vendored-a-qr-encoder-in-522-lines-148/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <summary>Кількість залежностей часу виконання лишилася на двох, а кодувальник є єдиним вкладеним компонентом у проєкті.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Документам потрібен був QR‑код із посиланням на онлайнову версію. Кожна доступна бібліотека це вміє, і взяти одну з них означало б додати третю залежність часу виконання до проєкту, що свідомо тримався двох — шаблонного рушія й рендерера PDF — з тим аргументом, що генератор документів має встановлюватися й через багато років.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Треба було або прийняти залежність, або реалізувати формат, і реалізацію треба було довести як правильну, а не просто таку, що дає щось квадратне й чорне.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Кодувальник має 522 рядки й реалізує ті частини специфікації, які насправді потрібні для цього вжитку: кодування в байтовому режимі, виправлення помилок за Ридом‑Соломоном над полем Галуа з 256 елементів із твірним многочленом, побудованим у потрібному степені, фіксовану розкладку модулів із її пошуковими взірцями, часовими взірцями та взірцями вирівнювання, інформацію про формат і версію, а також усі вісім взірців маскування даних, оцінених за чотирма штрафними правилами специфікації, тож обирається маска з найнижчим балом, а не стала. Саме перевірка зробила це захисним. Випробовувати кодувальник проти його власної логіки не доводить нічого, тож готову матрицю модулів зчитує назад декодувальник, написаний незалежно за порядком читання зі специфікації, і тест стверджує, що декодований рядок дорівнює вхідному. Це перетворює «воно дає правдоподібне зображення» на «воно дає код, що декодується в правильну URL‑адресу», і це перевіряють за кожного прогону, а не один раз оком і телефоном.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Кількість залежностей часу виконання лишилася на двох, а кодувальник є єдиним вкладеним компонентом у проєкті. Слід сказати прямо, що це не універсальна реалізація — вона підтримує ті режими й версії, які використовують документи, і нічого більше, а чесним обґрунтуванням є бюджет залежностей, а не якась заява, що результат кращий за зрілу бібліотеку.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Перенесла кожен рядок, звернений до користувача, з Python у дерево контенту з 874 файлів трьома мовами, знайшовши мертві переклади, чиєї мертвості ніхто не бачив, і перевірку, яка мовчки оцінювала третину досягнень.</title>
    <id>https://software.engineer.company/uk/portfolio/moved-every-user-facing-string-into-a-content-tree-152/</id>
    <link href="https://software.engineer.company/uk/portfolio/moved-every-user-facing-string-into-a-content-tree-152/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Міграції та модернізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Міграція та модернізація баз даних" scheme="https://software.engineer.company/uk/services/" />
    <summary>Прозу тепер можна редагувати, не торкаючись коду, і порівнювати між мовами підрахунком. Ціною є те, що додавання мови тепер однозначне, а не поступове — дерево…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Кожен рядок генератора, звернений до користувача, — кожне досягнення, кожен відгук, кожен заголовок розділу, кожне резюме, трьома мовами — жив усередині коду на Python. Це робить редагування речення зміною коду, робить перегляд перекладу різницею проти коду й унеможливлює побачити з першого погляду, чи мова повна. Це також ховає той режим відмови, що має значення: переклад може бути присутнім, хибним і недосяжним водночас.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Рядки треба було винести з коду до дерева вмісту, яке можна перерахувати, порівняти між мовами й перевірити, не запускаючи рендерера.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Результатом є 874 файли у каталозі вмісту, впорядкованих за видом, а потім за мовою: досягнення, відгуки, резюме, посади, компанії, регіони, категорії, послуги, профілі, рекомендації та фрагменти супровідних листів. Файли з полями через табуляцію, де одиницею є рядок з ідентифікатором, і окремі файли, де одиницею є абзац. Завантажувач читає їх під час збирання, і база даних збирається з них, тож дерево є джерелом, а база даних — похідною. Два висновки вийшли безпосередньо зі здатності рахувати. Деякі перекладені рядки більше не мали жодного англійського відповідника — мертві записи, яких ніщо не подавало і яких ніхто не міг би помітити, доки вони були вкладені в код, бо непосиланий ключ словника має точнісінько такий вигляд, як посиланий. А перевірка вмісту, що мала оцінювати кожне досягнення, читала лише ту підмножину, яку могла розв&amp;rsquo;язати, оцінювала тридцять сім із дев&amp;rsquo;яноста трьох і звітувала про успіх. Перетворення корпусу на каталог зробило обидва ці факти видимими як розбіжність у кількості файлів.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Прозу тепер можна редагувати, не торкаючись коду, і порівнювати між мовами підрахунком. Ціною є те, що додавання мови тепер однозначне, а не поступове — дерево робить неповну мову очевидною, і в цьому вся суть, але це також означає, що часткові переклади не можна тихо випускати, поки їх доробляють.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала міжмовну перевірку контенту, яка валиться, коли переклад губить число, вказане англійською, і коли мова вживає нотацію, якої не вживає, — знайшовши два данські описи без метрики і шістнадцять українських фрагментів, що цитували на англійський лад.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-cross-language-figure-and-notation-check-153/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-cross-language-figure-and-notation-check-153/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Data Governance" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Python" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інтернаціоналізація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Data Governance та якість даних" scheme="https://software.engineer.company/uk/services/" />
    <category term="Інтернаціоналізація та локалізація" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Вісімнадцять справжніх дефектів закрито, а разом із ними закрито й клас, бо кожен майбутній переклад порівнюється зі своїм англійським джерелом, перш ніж його…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Найшкідливіший різновид помилки перекладу в CV — не незграбна фраза. Це число, що зникає. Англійське речення, що заявляє п&amp;rsquo;ятдесятикратне поліпшення, перекладене реченням, яке каже «значно», є заявою, тихо відкликаною на одному ринку й збереженою на іншому, — і жодна перевірка орфографії, граматики чи людське читання самої лише цільової мови цього ніколи не помітить, бо перекладене речення є цілком доброю прозою.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Потрібна була перевірка, що читає мови одна проти одної, а не кожну окремо, на тих двох речах, які мають пережити переклад: числа й нотація, якою кожна мова їх записує.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Перевірка чисел витягує кожне число, відсоток, множник та одиницю з англійського рядка й вимагає, щоб кожне з них з&amp;rsquo;явилося в кожному перекладі того рядка, з формами множників, зіставленими для кожної мови окремо, а не збіганими буквально: англійська форма «у п&amp;rsquo;ятдесят разів» відповідає певній данській і певній українській вимові, і перевірка знає це зіставлення, а не вимагає самих лише цифр. Перевірка нотації є її дзеркалом: кожна мова має конвенції, які мусить вживати, і конвенції, яких вживати не має, зокрема десяткові розділювачі, групування тисяч і лапки. Українська бере лапки‑ялинки; англійські подвійні лапки в українському реченні є так само хибними, як пропущене число, і їх набагато легше внести копіюванням. Перший повний прогін виявив два данські описи, де показник, присутній в англійській, було втрачено, і шістнадцять українських фрагментів із лапками в англійському стилі.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Вісімнадцять справжніх дефектів закрито, а разом із ними закрито й клас, бо кожен майбутній переклад порівнюється зі своїм англійським джерелом, перш ніж його можна закомітити. Чого перевірка не вміє, так це судити про зміст: вона доводить, що число вижило і що пунктуація рідна, а переклад, що зберігає кожне число й водночас перевертає заяву навпаки, проходить її без зауважень.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала нативний клієнт обміну повідомленнями для macOS на Swift 6 і SwiftUI — 11 141 рядок у 53 файлах — поверх C‑інтерфейсу ядра на Rust, злінкованого як статичний архів із зафіксованої ревізії.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-native-macos-messaging-client-in-swift-6-154/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-native-macos-messaging-client-in-swift-6-154/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Full‑Stack розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Full‑Stack продуктова розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <summary>Рідний клієнт, що запускається як програма для Mac, використовує власні матеріали та елементи керування платформи й не несе вбудованого браузера.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Протокол обміну повідомленнями мав добре випробуване ядро, написане на Rust, і клієнти на кількох платформах, але настільний досвід на macOS був кросплатформною оболонкою — він не мав вигляду програми для Mac, не поводився як така й ніс середовище виконання, якого рідній програмі не потрібно. Ядро відкриває свою спроможність через C‑інтерфейс, а це означає, що будь‑яка мова, здатна викликати C, може на ньому будувати, і Swift здатен.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Рідного клієнта треба було збудувати безпосередньо на тому C‑інтерфейсі, поточною мовою платформи та її поточним інтерфейсним каркасом, із ядром, вкомпонованим усередину, а не постаченим поруч.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Програма має 11 141 рядок Swift у п&amp;rsquo;ятдесяти трьох файлах у цілі застосунку, збудована на SwiftUI з ядром, вкомпонованим як статичний архів, зібраний із закріпленої висхідної ревізії. Закріплення ревізії, а не стеження за гілкою, є тим рішенням, що робить збирання відтворюваним: C‑інтерфейс є контрактом, і рухоме ядро змінює контракт, не змінюючи жодного рядка Swift. Шарування тримає небезпечну поверхню малою — тонка обгортка володіє кожним вказівником і кожним рядком, що перетинає межу, моделі над нею є звичайними значеннями Swift, а інтерфейсний шар ніколи не бачить сирого вказівника. Усе, що повертає C‑інтерфейс, має правило володіння, і помилитися в одному з них означає або витік, або аварію без жодного попередження компілятора між ними, тож саме в обгортці живе вся дисципліна пам&amp;rsquo;яті проєкту. Збиранням керує виконавець завдань із п&amp;rsquo;ятдесятьма шістьма цілями, що охоплюють компіляцію ядра, збирання Swift, набори тестів, лінтери та пакування.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Рідний клієнт, що запускається як програма для Mac, використовує власні матеріали та елементи керування платформи й не несе вбудованого браузера. Те, чого не зроблено, слід зазначити: це не випущений реліз. Немає ні нотаризованого розповсюдження, ні каналу оновлень, і в інтерфейсі одна мова, тож це радше робоча програма, ніж продукт, який хтось інший використовує.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Спинила застосунок, що наповнював пам&#39;ять зі швидкістю 41 МБ за секунду — зафіксовані 111 ГБ стиснених сторінок на машині з 36 ГБ, — обмеживши кожен потік подій, підписуючись за типом події та поклавши бюджет швидкості на журналювання, що звело 610 996 рядків журналу до 1 411.</title>
    <id>https://software.engineer.company/uk/portfolio/stopped-an-application-filling-memory-at-41mb-a-second-155/</id>
    <link href="https://software.engineer.company/uk/portfolio/stopped-an-application-filling-memory-at-41mb-a-second-155/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Моніторинг та observability" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Надійність та моніторинг (SRE)" scheme="https://software.engineer.company/uk/services/" />
    <summary>Пам&#39;ять лишається рівною під тривалим навантаженням, і той самий сеанс, що давав 610 996 рядків журналу, дає 1 411.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Програма наповнювала пам&amp;rsquo;ять, доки операційна система її не вбивала. Зафіксований інцидент сягнув 111 ГБ стиснутих сторінок на машині з 36 ГБ, зростаючи приблизно на 41 МБ за секунду, а файл журналу за один короткий сеанс тримав 610 996 рядків. Машина в такому стані не повільна, вона непридатна — вбивство приходить після того, як підкачування вже змусило все інше на робочому столі перестати відповідати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Зростання треба було знайти, а не вгадати, і кожному необмеженому шляху треба було дати межу, бо одна обмежена черга поруч із трьома необмеженими не є виправленням.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Причин‑множників було три, і саме множення пояснює, чому це відбувалося так швидко. Потік подій із ядра споживався без жодної межі, тож події надходили швидше, ніж інтерфейс міг їх застосувати, і доробок утримувався, а не відкидався. Кожен передплатник отримував кожну подію й фільтрував після цього, тож вартість однієї події множилася на кількість слухачів, і фільтрування кожного слухача виділяло пам&amp;rsquo;ять. А журналювання було небюджетованим, тож кожна подія породжувала рядки журналу — і це складений доданок, бо обсяг журналювання був пропорційним до обсягу того, що йшло не так. Виправлення взялося за всі три: обмежені буфери з явною політикою того, що стається за їх заповнення, передплата за типом події, тож слухача будять лише для подій, яких він хоче, і бюджет швидкості на журналювання, що згортає повтори, а не пише кожен. Регресійний тест жене високу швидкість подій і стверджує, що стеля пам&amp;rsquo;яті тримається, тож межа є властивістю збирання, а не коментарем.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Пам&amp;rsquo;ять лишається рівною під тривалим навантаженням, і той самий сеанс, що давав 610 996 рядків журналу, дає 1 411. Чесним зауваженням є те, що бюджет швидкості на журналювання відкидає інформацію: коли щось іде не так швидко, запис про це тепер навмисно неповний, і це обмін, зроблений свідомо проти альтернативи, якою є машина, що спиняється.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Прийняла повну сувору паралельність Swift 6 без акторів, перекинувши місток від блокувального циклу подій C до головного актора через одного виробника, одного споживача й один порядок — після встановлення, що задача на подію губить порядок, від якого залежить інтерфейс.</title>
    <id>https://software.engineer.company/uk/portfolio/adopted-swift-6-strict-concurrency-over-a-c-event-loop-156/</id>
    <link href="https://software.engineer.company/uk/portfolio/adopted-swift-6-strict-concurrency-over-a-c-event-loop-156/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Архітектура рішень" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Оптимізація продуктивності" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="Архітектура платформи та рішень" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічне лідерство та консалтинг" scheme="https://software.engineer.company/uk/services/" />
    <summary>Програма компілюється за повної суворої перевірки паралельності без придушень, а впорядкованість подій є структурною властивістю, а не сподіванням.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Повна сувора перевірка паралельності у Swift 6 перетворює гонитви за даними на помилки компіляції замість переривчастих аварій. Впроваджувати її проти бібліотеки на C — саме там, де стає важко: цикл подій ядра є блокувальним викликом, що має вічно виконуватися поза головним потоком, а значення, які він повертає, є вказівниками без жодних гарантій щодо паралельності. Компілятор не може міркувати про це все й відхилятиме всі, доки межу не буде описано явно.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Повну перевірку треба було ввімкнути без жодних запасних лазівок, а це означало спроєктувати перехід від блокувального циклу на C до головного актора, а не обставляти його анотаціями.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Очевидним підходом є актор на підсистему, і його відкинули за вимірюванням, а не за смаком. Породження задачі на кожну вхідну подію дозволяє середовищу виконання планувати їх у будь‑якому порядку, а потік подій ядра є впорядкованим — подія «повідомлення змінено», що обганяє подію «повідомлення створено», на яку вона посилається, дає інтерфейс, що показує редагування чогось, чого ще не існує. Повторний вхід в актора робить це гіршим, а не кращим, бо актор може призупинитися посеред методу й обробити інший виклик. Те, що це замінило, є навмисно простим: один потік‑виробник, що володіє блокувальним циклом, один споживач, одна черга між ними та єдиний стрибок на головного актора наприкінці. Порядок зберігається, бо шлях рівно один і ніщо нічого не обганяє. Небезпечні типи, що перетинають цю межу, загорнуто в типи, чию потокобезпеку стверджують на обгортці, а не припускають, і твердження задокументовано разом із тим, чому воно чинне: вказівником володіє один потік, і його копіюють, перш ніж передати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Програма компілюється за повної суворої перевірки паралельності без придушень, а впорядкованість подій є структурною властивістю, а не сподіванням. Ціною є те, що задум менш паралельний, ніж міг би бути: усе стікається через одного споживача, і якщо той споживач колись стане вузьким місцем, виправлення вимагатиме заново вивести, які події можна безпечно переставляти, а це саме той аналіз, якого це дозволило уникнути.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Написала парсер, який читає справжній C‑заголовок на 7 308 рядків і перевіряє кожне місце виклику, кожну константу переліку й те, що кожен клас‑власник вказівника є final, після того як рукописний заголовок‑заглушка дозволив викликам до трьох вилучених функцій скомпілюватися, злінкуватися й впасти.</title>
    <id>https://software.engineer.company/uk/portfolio/wrote-a-parser-that-verifies-every-ffi-call-site-157/</id>
    <link href="https://software.engineer.company/uk/portfolio/wrote-a-parser-that-verifies-every-ffi-call-site-157/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Клас дефектів, що спричинив початкову аварію, не може повторитися, бо застаріле посилання тепер є відмовою збирання, а не відмовою під час виконання.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; На початку проєкту C‑інтерфейс представляв рукописний заголовний файл, що описував функції, яких очікувала програма. Той заголовок компілювався, програма зв&amp;rsquo;язувалася, а виклики трьох функцій, яких у ядрі більше не існувало, доходили до моменту виклику й аварійно завершувалися. І компілятор, і компонувальник задовольнилися описом бібліотеки замість самої бібліотеки, а розрив виявився лише під час виконання.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Справжній заголовок — 7 308 рядків і 268 оголошень — мав стати авторитетом, і кожне його використання в коді Swift треба було звіряти з ним автоматично, а не переглядом.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Перевіркою є розбирач, що читає справжній висхідний заголовок і будує множину функцій, констант переліку й типів, які той оголошує, а потім читає код Swift і розв&amp;rsquo;язує кожне місце виклику та кожне посилання на константу проти цієї множини. Виклик функції, якої заголовок не оголошує, валить збирання. Посилання на константу переліку, яку перейменували, валить збирання. Поточне число — 132 з 268 оголошень, на які є посилання, і знати, які 136 не використовуються, саме собою корисно, бо це каже точно, якої частини ядра клієнт не досяг. Розбирач також примусово застосовує правило, якого не може компілятор: кожен клас Swift, що володіє вказівником у ядро, має бути фінальним. Нефінальний клас, що володіє вказівником, можна успадкувати, а підклас, що перевизначає деініціалізацію або додає власний час життя, змінює момент звільнення вказівника — використання після звільнення без жодного небезпечного ключового слова поблизу. Правило перевіряють за іменем по всьому дереву.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Клас дефектів, що спричинив початкову аварію, не може повторитися, бо застаріле посилання тепер є відмовою збирання, а не відмовою під час виконання. Обмеженням є те, що розбирач розуміє оголошення заголовка, а не його семантику: він доводить, що функція існує з відповідним іменем, а функція, чиє значення чи правило володіння змінилося вище за течією зі збереженням сигнатури, проходить без зауважень.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Назвала кожен суто піктограмний елемент керування в інтерфейсі для зчитувачів екрана після того, як кнопка надсилання оголошувалася як «arrow up circle, button», і написала лінтер, що вимагає підпис у межах восьми рядків від піктограми.</title>
    <id>https://software.engineer.company/uk/portfolio/named-all-seventeen-interface-icons-for-screen-readers-159/</id>
    <link href="https://software.engineer.company/uk/portfolio/named-all-seventeen-interface-icons-for-screen-readers-159/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <summary>Усі сімнадцять елементів керування оголошують свою функцію, і вісімнадцятий не можна додати без неї.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Інтерфейс використовував системні символи для своїх елементів керування, а символ без мітки доступності екранний читач озвучує його власним внутрішнім іменем. Кнопка надсилання оголошувалася як «стрілка вгору коло, кнопка». Так само робив кожен інший елемент керування лише з піктограмою в програмі, кожен по‑своєму — сімнадцять із них описували власний малюнок замість своєї функції.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Кожен елемент керування лише з піктограмою потребував мітки, що описує, що він робить, і виправлення мало прийти з перевіркою, бо наступна додана піктограма інакше внесла б дефект назад негайно.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Кожному із сімнадцяти надали мітку, що називає дію, а не форму, і там, де значення елемента залежить від стану, мітка йде за станом, а не є сталою. Перевірка є тією частиною, яку варто описати, бо загального правила «чи це доступно» для цього не існує. Лінтер шукає конструкцію, що створює елемент керування лише з піктограмою, і далі вимагає мітки доступності в межах восьми рядків від неї. Вісім рядків є навмисно грубою евристикою, і її обрано вимірюванням: вона достатньо довга, щоб охопити кожен законний спосіб, яким кодова база пише один із цих елементів разом із його модифікаторами, і достатньо коротка, щоб мітка, приєднана до іншого подання нижче, її випадково не задовольнила. Точне правило тут мало б розуміти ланцюжки модифікаторів SwiftUI як дерево, а дешеве правило близькості ловить справжню помилку — а це не хибно підписаний елемент, це непідписаний.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Усі сімнадцять елементів керування оголошують свою функцію, і вісімнадцятий не можна додати без неї. Неточність правила є реальною й зазначена там, де його визначено: його може задовольнити мітка на сусідньому поданні, тож воно доводить, що мітка існує поруч, а не що мітка правильна, і для правильності досі потрібно, щоб хтось її послухав.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала систему дизайну на 48 токенів поверх власного скляного матеріалу платформи й написала лінтер, який відхиляє магічне число, жорстко задений розмір шрифту чи анімацію, що ігнорує настройку зменшеного руху.</title>
    <id>https://software.engineer.company/uk/portfolio/built-a-48-token-design-system-160/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-a-48-token-design-system-160/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сорок вісім токенів описують увесь інтерфейс, вигляд іде за системою, і жодне з трьох руйнувань не можна закомітити.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Інтерфейс, збудований додаванням подань, накопичує значення: радіус заокруглення тут, шрифт у чотирнадцять пунктів там, анімація на дві десятих секунди десь іще. Кожне окремо є розумним, а разом вони є дизайном, якого не можна змінити, бо не існує такої речі, як «радіус заокруглення», щоб її змінити, — їх сорок, злегка різних, розсипаних по п&amp;rsquo;ятдесяти файлах.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Візуальний словник треба було скоротити до іменованої множини, вираженої проти власного матеріалу платформи, а не винайденої заново, і захищеної перевіркою, щоб він лишався скороченим.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Системою є сорок вісім токенів у шести групах: відступи, типографіка, колір, радіус, підняття та рух. Колір і матеріал збудовано на семантичних кольорах платформи та її скляному матеріалі, а не на сталих значеннях, і саме це змушує інтерфейс іти за системним виглядом, акцентним кольором і налаштуваннями контрасту без жодного коду, що за ними стежить. Типографіка відображається на текстові стилі платформи, тож вона масштабується з уподобою розміру в користувача замість прив&amp;rsquo;язки до пунктового значення. Лінтер відхиляє три речі: числовий літерал там, де належить токен відступу чи радіуса, жорстко заданий кегль будь‑де і анімацію, оголошену без шанування уподоби зменшеного руху. Третя є тією, що інакше руйнувалася б найшвидше, бо анімацію додають у мить наведення блиску, і саме перевірку уподоби пропускають — тож правило робить саму анімацію неможливою для написання без неї, а не просить когось пам&amp;rsquo;ятати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сорок вісім токенів описують увесь інтерфейс, вигляд іде за системою, і жодне з трьох руйнувань не можна закомітити. Межею є те, що система токенів обмежує узгодженість, а не якість, — тепер усе пасує одне до одного, а пасувати не те саме, що бути добре спроєктованим, і це судження не виносить жоден лінтер у цьому проєкті.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Дістала ту половину ядра обміну повідомленнями, якої застосунок ніколи не використовував, — передавання резервної копії, зникомі повідомлення, редагування та повторне надсилання, підтверджені запрошення, проксі та політику шифрування, — ведучи кожен тест проти справжньої бібліотеки без заглушок.</title>
    <id>https://software.engineer.company/uk/portfolio/reached-the-unused-half-of-the-messaging-core-161/</id>
    <link href="https://software.engineer.company/uk/portfolio/reached-the-unused-half-of-the-messaging-core-161/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="API та інтеграції" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Надійність і резервне копіювання" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Backend- та API‑розробка" scheme="https://software.engineer.company/uk/services/" />
    <category term="DevOps та автоматизація CI/CD" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <summary>Раніше недосяжну половину ядра тепер ганяють тести проти справжньої бібліотеки, а обгортка несе найвищу підлогу в проєкті.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Клієнт використовував приблизно половину того, що пропонує ядро обміну повідомленнями. Невикористана половина не була маловідомою — перенесення резервних копій між пристроями, зникомі повідомлення, редагування та повторне надсилання повідомлень, перевірені запрошувальні посилання, налаштування проксі та політика шифрування для розмови. Кожне з цього є можливістю, якої очікував би користувач, і кожне було невипробуваною ділянкою C‑інтерфейсу, а це небезпечніший факт, бо невипробувана ділянка C‑інтерфейсу — саме там, де живуть помилки володіння.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Недосяжну спроможність треба було задіяти й покрити, і тести мали виконуватися проти справжньої бібліотеки, а не проти заміщувача.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Прийнятим правилом було жодних імітацій для ядра. Імітація C‑інтерфейсу кодує переконання розробника про те, що робить бібліотека, а кожен вартий пошуку дефект тут є місцем, де це переконання хибне, — тож пройдений тест на імітації є свідченням про імітацію. Натомість тести створюють справжні облікові записи в тимчасових каталогах, ганяють справжню бібліотеку і стверджують про те, що вона насправді повертає, і кожен набір прибирає власний стан. Саме це зробило покриття змістовним: задіяти перенесення резервних копій означало обробити машину станів справжнього перенесення та її шляхи відмов, а задіяти перевірені запрошення означало сконструювати справжній формат посилання й дати бібліотеці його розібрати. Підлоги покриття задано на кожен шар окремо, а не одним числом: вісімдесят чотири відсотки для обгортки ядра, сімдесят п&amp;rsquo;ять для допоміжних функцій і шістдесят п&amp;rsquo;ять для моделей, з тим міркуванням, що шар, який торкається сирих вказівників, слід тримати найвище, а модель, яка здебільшого складається зі збережених властивостей, не варто набивати тестами заради середнього.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Раніше недосяжну половину ядра тепер ганяють тести проти справжньої бібліотеки, а обгортка несе найвищу підлогу в проєкті. Ціною є швидкість і передбачуваність: тести проти справжньої бібліотеки повільніші за імітації, і вони можуть падати з причин середовища, а це ціна за їхню здатність падати зі справжніх.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Переписала повідомлення про помилки застосунку за письмовим стандартом тону після того, як відмовлений вхід звинуватив користувача в друкарській помилці, тоді як провайдер насправді вимагав пароль для застосунку, і покрила це тестом, який називає провайдера.</title>
    <id>https://software.engineer.company/uk/portfolio/rewrote-the-error-messages-against-a-tone-standard-162/</id>
    <link href="https://software.engineer.company/uk/portfolio/rewrote-the-error-messages-against-a-tone-standard-162/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Frontend‑розробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Документація" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Продукт і вимоги" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Продуктова стратегія та вимоги" scheme="https://software.engineer.company/uk/services/" />
    <category term="Технічна документація" scheme="https://software.engineer.company/uk/services/" />
    <summary>Поверхня помилок дотримується зазначеного стандарту, а випадок, що до нього спонукав, покрито тестом, який падає на старому тексті.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Вхід до великого поштового провайдера не вдався, і програма сказала користувачеві, що його пароль хибний. Він не був хибним. Той провайдер вимагає окремого пароля застосунку для сторонніх клієнтів і відхиляє пароль облікового запису незалежно від того, наскільки ретельно його набрано. Повідомлення відправило користувача перенабирати те, що ніколи не могло спрацювати, а справжня вказівка — піти й створити інший різновид пароля — не з&amp;rsquo;являлася ніде.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Повідомлення про помилки треба було переписати за письмовим стандартом, а не латати по одному, бо це було видимим випадком звички, що проходила крізь усі них.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Стандарт має три вимоги: скажи, що сталося, ніколи не натякай, що користувач зробив щось не так, коли причина деінде, і дай наступну дію, коли така є. Застосований до всієї поверхні помилок, він показав, що більшість повідомлень порушує щонайменше одну — кілька були рядком помилки нижчої бібліотеки, пропущеним наскрізь, а він описує стан для програміста, а не ситуацію для людини. Випадок із провайдером переписали так, щоб назвати провайдера, зазначити, що він вимагає окремого пароля застосунку для інших клієнтів, і сказати, де такий створити. Тест є тим, що не дає цьому повернутися, і він навмисно конкретний: він жене невдалий вхід проти того провайдера й стверджує, що повідомлення містить ім&amp;rsquo;я провайдера та вислів, що описує потрібний тип облікових даних. Тест, що стверджував би лише появу якоїсь помилки, пройшов би й на початковому хибному повідомленні, тож твердження стоїть на вмісті, а це єдина частина, що колись була зламана.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Поверхня помилок дотримується зазначеного стандарту, а випадок, що до нього спонукав, покрито тестом, який падає на старому тексті. Нерозв&amp;rsquo;язаним лишається масштаб: стандарт примусово тримають переглядом і одним тестом на одне повідомлення, а інші провайдери зі своїми особливими вимогами не мають рівноцінного тесту, тож клас задокументовано, а не закрито.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Побудувала набори піктограм і фавіконів компанії з двох рукотворних малюнків, де кожен похідний ресурс перегенеровується скриптом, а перевірка валиться, коли похідний файл закомічено раніше за своє джерело.</title>
    <id>https://software.engineer.company/uk/portfolio/built-the-visual-identity-from-two-drawings-164/</id>
    <link href="https://software.engineer.company/uk/portfolio/built-the-visual-identity-from-two-drawings-164/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="UX / UI‑дизайн" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Автоматизація та CI/CD" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Бренд і маркетинг" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Дизайн‑системи та UI" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Тестування та QA" scheme="https://software.engineer.company/uk/categories/" />
    <category term="UI/UX‑дизайн та дизайн‑системи" scheme="https://software.engineer.company/uk/services/" />
    <category term="Бренд, маркетинг та SEO" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <summary>Два малюнки виробляють кожну опубліковану піктограму, перегенерація є однією командою, а застарілий ресурс валить збирання.</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Візуальну ідентичність малої компанії зазвичай купують, генерують або збирають зі стокових матеріалів, і результатом є ідентичність, що не належить нікому. Альтернативна проблема гірша: рукотворна графіка, що існує лише як експортовані файли, де вихідний малюнок втрачено, експорти редагують безпосередньо, і протягом року версії в ужитку розходяться між собою, а оригіналу, який це владнав би, не лишилося.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Ідентичність треба було намалювати, а не роздобути, і конвеєр від малюнка до опублікованого ресурсу мав бути відтворюваним, щоб кожен файл на сайті виводився, а не зберігався.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; В основі згенерованого зображального матеріалу лежать два рукотворні малюнки — знак компанії та шестірня, що стала фавіконом, — і кожну піктограму, яку публікує сайт, вироблено з них. Знак є растровим малюнком; шестірня є вектором. З них скрипти виробляють кожну похідну форму: набір favicon у потрібних розмірах, дотикові піктограми, зображення для соціальних попереднів, адаптивні растрові варіанти в кожній ширині й у кожному сучасному форматі та версії для конкретних тем. Генерація є завданням, яке може виконати будь‑хто, тож питання «звідки взявся цей файл» має відповідь, що є командою. Перевірка застарілості є тим шматком, що тримає це разом: вона порівнює час зміни кожного похідного ресурсу з його джерелом і падає, коли похідний файл старіший, і це ловить саме ту відмову, задля запобігання якій цей задум існує, — хтось редагує джерело, забуває перегенерувати, і опублікований сайт далі показує графіку, що більше не відповідає оригіналові. Правило, що похідні файли ніколи не редагують вручну, зазначено там, де живуть джерела.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Два малюнки виробляють кожну опубліковану піктограму, перегенерація є однією командою, а застарілий ресурс валить збирання. Компромісом є жорстка залежність від набору інструментів: похідні файли закомічено, тож сайт збирається будь‑де, але зміна ідентичності вимагає, щоб генераційне знаряддя досі працювало, а вихідний формат, який перестане читатися, забере всю ідентичність із собою.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Опублікувала сайт як onion‑дзеркало в Tor на читабельній адресі, що починається з engineer, з ключем, згенерованим поза хостом, тож він ніколи не потрапив ні до цього репозиторію, ні на ноутбук, і лишила ці двері єдиними з чотирьох, які ніколи не рахують.</title>
    <id>https://software.engineer.company/uk/portfolio/published-the-site-as-a-tor-onion-mirror-on-a-readable-168/</id>
    <link href="https://software.engineer.company/uk/portfolio/published-the-site-as-a-tor-onion-mirror-on-a-readable-168/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-10-09T14:31:15+02:00</published>
    <category term="Linux та сервери" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Безпека" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Веброзробка" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Інфраструктура" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/categories/" />
    <category term="Infrastructure as Code" scheme="https://software.engineer.company/uk/services/" />
    <category term="Безпека та керування доступом" scheme="https://software.engineer.company/uk/services/" />
    <category term="Розробка вебсайтів та CMS" scheme="https://software.engineer.company/uk/services/" />
    <category term="Системне адміністрування" scheme="https://software.engineer.company/uk/services/" />
    <summary>Сайт має четверо дверей до однієї збірки, і ці -- єдині, яких ніколи не рахують. Запити Gemini та з&#39;єднання Gopher підраховують щодня без адреси й без шляху; в…</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Ситуація.&lt;/strong&gt; Сайт уже відповідав на трьох протоколах з однієї збірки. Читач, якому треба було дістатися до нього, не виказуючи, що він дістався, усе ще робив гак через вихідний вузол до звичайної адреси, а це слабше за власні двері. Очевидне заперечення проти четвертих дверей &amp;ndash; це фаєрвол, і воно не діє: демон анонімності виходить у мережу, будуючи вихідні ланцюги, тож ніхто не дзвонить усередину, жоден порт не відкривається, і жодному з двох шарів фаєрвола нема чого узгоджувати.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Завдання.&lt;/strong&gt; Дзеркало мало віддавати ті самі сторінки, що й звичайна адреса, бути опублікованим там, де опубліковані інші дзеркала, нести адресу, яку людина може прочитати вголос, а не випадковий рядок, і ніколи не дозволити приватному ключу, який і є адресою, торкнутися цього репозиторію чи ноутбука.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Дія.&lt;/strong&gt; Роль встановлює демон із власного пакета дистрибутива, пише конфігурацію з вимкненим вихідним портом проксі й відмовляється перезаписувати особу, якої не генерувала, &amp;ndash; тож ключ, покладений рукою, просто використовується. Читабельну адресу не можна обрати, лише знайти: адреса &amp;ndash; це відкритий ключ у base32, тож префікс купують, генеруючи пари ключів, доки одна з них випадково не закодує потрібні літери, і кожен символ коштує в тридцять два рази більше за попередній. Куплений префікс читається як власна назва компанії. Адреса &amp;ndash; це оголошене значення в інвентарі, і кожне зведення стверджує, що справжній файл особи на хості збігається з ним, тож підмінений ключ зі застарілим оголошенням валить запуск, а не мовчить. Ключ ловлять обидві сторожі секретів, після того як було виміряно, що очевидний шаблон для файлу ключа збігається з ключем розгортання й проминає цей. Виведення з обігу випадкової адреси, з якою дзеркало вийшло, було поетапним переходом, а не перемикачем, тож опублікована адреса працювала, доки публікувалася читабельна. Крок, що видавався останнім, ним не був: ключ ліг правильно, а зведення повідомило про відсутність змін, бо ніщо ще не називало нову теку, тож нова адреса так і не була опублікована &amp;ndash; тепер роль валиться на особі на диску, якої не називає жодна служба.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Результат.&lt;/strong&gt; Сайт має четверо дверей до однієї збірки, і ці &amp;ndash; єдині, яких ніколи не рахують. Запити Gemini та з&amp;rsquo;єднання Gopher підраховують щодня без адреси й без шляху; в onion немає лічильника й немає прапорця, щоб його додати, бо порахувати там читача &amp;ndash; це саме те єдине, заради запобігання чому протокол існує, і сліпота тут ціна позиції, а не прогалина у звітності. Дзеркало окупилося ще й як друга думка: його перші читачі сиділи на іншому рушії браузера, який не реалізує керовану прокруткою анімацію, на яку спирався колофон, тож кожен із них отримав колофон, намальований поверх головної сторінки. Це був справжній дефект звичайного сайту, знайдений аудиторією, яка не мала іншого способу про нього повідомити.&lt;/p&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Підкреслення, яке не обходило літери</title>
    <id>https://software.engineer.company/uk/notes/safari-underline-font-subset/</id>
    <link href="https://software.engineer.company/uk/notes/safari-underline-font-subset/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-09-28T00:00:00Z</published>
    <summary>Safari проводив наші підкреслення крізь кожен виносний елемент. Причиною був кириличний підшрифт на сторінках, які його не завантажують.</summary>
    <content type="html">&lt;p&gt;Наш власний сайт підкреслює кожне посилання й дозволяє браузеру вирізати&#xA;проміжок там, де хвостик літери перетинає лінію, — &lt;code&gt;g&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, кома. У Safari&#xA;цього не відбувалося. Лінія йшла просто крізь них. І так було на англійських та&#xA;данських сторінках відтоді, як сайт став&#xA;&lt;span class=&#34;ann ann-n ann-blue&#34; data-note=&#34;вада, про яку ніхто не повідомляє, бо вона просто має дешевий вигляд&#34;&gt;багатомовним&lt;/span&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Причиною були три оголошення шрифту для абетки, яку ті сторінки ніколи не&#xA;завантажують.&lt;/p&gt;&#xA;&lt;h2 id=&#34;що-браузер-має-робити&#34;&gt;Що браузер має робити&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;text-decoration-skip-ink&lt;/code&gt; — це властивість, яка піднімає підкреслення над&#xA;нижнім виносним елементом. Вона ввімкнена за замовчуванням, і роками відповіддю&#xA;на «моє підкреслення має неправильний вигляд» було взятися за&#xA;&lt;code&gt;text-underline-offset&lt;/code&gt; і посунути лінію нижче. Це хибний рефлекс: зсув лінії&#xA;змінює дизайн, а бракувало насправді саме проміжку.&lt;/p&gt;&#xA;&lt;p&gt;Перш ніж дійти до цікавого, ми знайшли дві справжні причини, і обидві варті&#xA;уваги.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Підкреслення завтовшки &lt;code&gt;1px&lt;/code&gt; отримує проміжок розміром &lt;code&gt;1px&lt;/code&gt;.&lt;/strong&gt; Розрив, який&#xA;вирізає рушій, пропорційний товщині лінії, що його вирізає. Наш стиль&#xA;зафіксував товщину на одному пікселі, і це лишало близько 0,6px повітря з&#xA;кожного боку штриха — технічно проміжок, візуально лінія просто крізь літеру.&#xA;&lt;code&gt;text-decoration-thickness: auto&lt;/code&gt; змасштабував обидві величини разом і збільшив&#xA;проміжок з 3,5px до 12,4px, не зсунувши підкреслення ані на піксель.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;from-font&lt;/code&gt; — не той безпечний варіант, яким здається.&lt;/strong&gt; Він читає товщину,&#xA;яку оголошує сам шрифт, а Ubuntu оголошує 0,056em для Light, 0,020em для&#xA;Medium і 0,120em для Bold — родина, у якої лінія Medium важить менше за&#xA;половину лінії Light. На великих розмірах це шестипіксельна лінія поряд із&#xA;двопіксельною на одній сторінці.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Це виправило Chrome. Safari й далі вів лінію крізь усе.&lt;/p&gt;&#xA;&lt;h2 id=&#34;частина-яка-забрала-найбільше-часу&#34;&gt;Частина, яка забрала найбільше часу&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Ми виміряли це як належить: запустити справжній Safari, перефарбувати&#xA;підкреслення, зробити знімок екрана у восьмикратному масштабі й порахувати&#xA;пікселі, де лінія уривається й починається знову.&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;намальована товщина&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;проміжок навколо виносного елемента&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;svg class=&#34;browser-mark ti-brand&#34; aria-hidden=&#34;true&#34;&gt;&lt;use href=&#34;/icons/browsers.0ba2bcfa23ee31cd1f0f0c26d989e16b7db9ff8763cfad34dbb801ae81339da6.svg#ti-brands-chrome&#34;&gt;&lt;/use&gt;&lt;/svg&gt;&#xA;Chrome&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;2,00px&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;5,8 / 12,5 / 6,3px&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;&lt;svg class=&#34;browser-mark ti-brand&#34; aria-hidden=&#34;true&#34;&gt;&lt;use href=&#34;/icons/browsers.0ba2bcfa23ee31cd1f0f0c26d989e16b7db9ff8763cfad34dbb801ae81339da6.svg#ti-brands-safari&#34;&gt;&lt;/use&gt;&lt;/svg&gt;&#xA;Safari&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;1,38px&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;1,8 / 1,0 / 1,0px&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Отже, Safari таки вирізав проміжок. Просто вшестеро вужчий за Chrome, а в&#xA;розмірі для читання проміжок в один піксель — це не проміжок. Гірше: звичний&#xA;важіль лише погіршував справу. За товщини 3px Safari падав із трьох проміжків до&#xA;одного, за 4px — до жодного, бо він не масштабує проміжок разом із лінією. Він&#xA;фіксує його приблизно на 0,07em за будь-якого розміру, тоді як Chrome дає 0,6em.&lt;/p&gt;&#xA;&lt;p&gt;Ми перебрали проти нього близько двадцяти оголошень — &lt;code&gt;skip-ink: all&lt;/code&gt;, обидва&#xA;застарілі написання властивості, кожну товщину від половини пікселя до чотирьох,&#xA;&lt;code&gt;text-underline-position&lt;/code&gt;, &lt;code&gt;font-smoothing&lt;/code&gt;, &lt;code&gt;text-rendering&lt;/code&gt;, &lt;code&gt;paint-order&lt;/code&gt;.&#xA;Ніщо не розширило проміжок. Чесний висновок на той момент був такий: WebKit&#xA;просто обмежує проміжок, і зі стилів більше нічого не вдіяти.&lt;/p&gt;&#xA;&lt;p&gt;Той висновок виявився хибним, а зламав його&#xA;&lt;a href=&#34;https://github.com/fontsource/fontsource/issues/1096&#34;&gt;звіт про ваду проти шрифтового проєкту&lt;/a&gt;:&#xA;Safari ігнорує skip-ink, коли шрифт завантажено з нелатинською підмножиною.&lt;/p&gt;&#xA;&lt;h2 id=&#34;справжня-причина&#34;&gt;Справжня причина&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Сайт віддає Ubuntu шістьма частинами — три накреслення латиницею, три&#xA;кирилицею, — щоб українська сторінка була набрана тим самим шрифтом, що й&#xA;англійська, а не відкочувалася до того, що запропонує система. Кожна частина&#xA;оголошує діапазон символів, який покриває, і браузер завантажує лише ті&#xA;частини, які сторінці справді потрібні.&lt;/p&gt;&#xA;&lt;p&gt;Усі шість були оголошені під однією назвою родини — це найочевидніший спосіб це&#xA;записати. І саме він є спусковим гачком, зафіксованим як&#xA;&lt;a href=&#34;https://bugs.webkit.org/show_bug.cgi?id=255159&#34;&gt;вада WebKit 255159&lt;/a&gt;: &lt;strong&gt;коли&#xA;одне накреслення в родині оголошує нелатинський діапазон символів, Safari&#xA;погіршує skip-ink для кожного символу цієї родини&lt;/strong&gt; — зокрема для латинського&#xA;тексту на сторінці, яка ніколи не завантажує той інший файл.&lt;/p&gt;&#xA;&lt;p&gt;Англійська сторінка малювала свої підкреслення погано, бо десь у стилях існувало&#xA;українське оголошення шрифту. Коли ми видалили ті три рядки під час виконання й&#xA;не змінили більше нічого, проміжки зросли з 1,8/1,0/1,0px до 4,5/11,0/5,0px.&lt;/p&gt;&#xA;&lt;h2 id=&#34;виправлення&#34;&gt;Виправлення&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Дайте другій системі письма власну назву родини й назвіть її у стеку шрифтів&#xA;після першої:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-css&#34; data-lang=&#34;css&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;font-face&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;font-family&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;UbuntuCyrillic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;   &lt;span class=&#34;c&#34;&gt;/* було: Ubuntu */&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;src&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ubuntu_300_cyrillic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nc&#34;&gt;woff2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;woff2&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;unicode-range&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;0400-045F&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nt&#34;&gt;U&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;0490-0491&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;root&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;--body-font&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Ubuntu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;UbuntuCyrillic&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;system-ui&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;sans-serif&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Латинська літера знаходиться в першій родині й ніколи не доходить до другої.&#xA;Кирилична проминає першу, де такого гліфа немає, і потрапляє в другу, а не в&#xA;системний шрифт. Діапазони символів і далі вирішують, що завантажується, тож в&#xA;завантаженні не змінюється нічого: англійські та данські сторінки беруть три&#xA;латинські файли й жодного кириличного, українські — навпаки.&lt;/p&gt;&#xA;&lt;p&gt;Три перейменовані оголошення й один запис у стеку. Проміжки в Safari зросли до&#xA;4,5/11,0/5,0px, Chrome лишився недоторканим, підкреслення не зрушило з місця, а&#xA;українська й далі набирається в Ubuntu з тими самими ширинами.&lt;/p&gt;&#xA;&lt;h2 id=&#34;що-ми-сказали-б-наступному&#34;&gt;Що ми сказали б наступному&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Вимірювання skip-ink справедливе лише для того рушія, який його дав.&lt;/strong&gt; Ми&#xA;мали таблицю чисел, правильний діагноз і справжнє виправлення — і все це було&#xA;Chromium. Знімок екрана, який відкрив справу наново, надійшов від людини, яка&#xA;подивилася на сторінку.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Беріться за товщину раніше, ніж за зсув.&lt;/strong&gt; Ширший проміжок зберігає дизайн;&#xA;зсув лінії вниз його замінює.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ділити шрифт за системами письма — правильно, але поділ має бути й у назві&#xA;родини.&lt;/strong&gt; Одна назва на кілька систем письма читається краще й коштує вам&#xA;skip-ink у Safari. Злити їх назад має вигляд прибирання, а є регресом.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Завантаження ніколи не було проблемою.&lt;/strong&gt; Будь-яка інтуїція підказує, що&#xA;сторінка, яка малюється погано через кириличний шрифт, мусить завантажувати&#xA;щось зайве. Вона не завантажувала. Досить було самого оголошення.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;джерела&#34;&gt;Джерела&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://bugs.webkit.org/show_bug.cgi?id=255159&#34;&gt;Вада WebKit 255159 — &lt;code&gt;text-decoration-skip-ink&lt;/code&gt; і підмножини шрифтів&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/fontsource/fontsource/issues/1096&#34;&gt;Issue 1096 у Fontsource, який назвав спусковий гачок&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration-skip-ink&#34;&gt;MDN: &lt;code&gt;text-decoration-skip-ink&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range&#34;&gt;MDN: &lt;code&gt;unicode-range&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
  </entry>
  <entry>
    <title>Як відкрити dApp у мобільних гаманцях Solana</title>
    <id>https://software.engineer.company/uk/notes/solana-mobile-wallet-deeplinks/</id>
    <link href="https://software.engineer.company/uk/notes/solana-mobile-wallet-deeplinks/" rel="alternate" type="text/html" />
    <updated>2026-10-09T14:31:15+02:00</updated>
    <published>2026-08-10T00:00:00Z</published>
    <summary>Чому browse-deeplinks до Phantom, Solflare і Backpack не спрацьовують на мобільних, і точні формати, правила запуску та виправлення, які змушують їх працювати.</summary>
    <content type="html">&lt;p&gt;React-dApp, побудований на &lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt;, без проблем&#xA;під&amp;rsquo;єднує десктопні гаманці, але на телефоні той самий потік розсипається:&#xA;гаманець має відкрити dApp у власному вбудованому браузері, а deeplinks, які&#xA;мали б це зробити, просто мовчки не спрацьовують. Backpack виводить на&#xA;сторінку «завантажте застосунок»; Solflare відкриває застосунок, але ніколи —&#xA;сайт; здається, що не працює жоден варіант. Ми розібрали проблему на частини,&#xA;і виявилося, що це чотири окремі проблеми з одним спільним симптомом.&lt;/p&gt;&#xA;&lt;h2 id=&#34;чотири-проблеми&#34;&gt;Чотири проблеми&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Посилання для Backpack було сформоване неправильно.&lt;/strong&gt; Єдиний&#xA;задокументований формат —&#xA;&lt;code&gt;https://backpack.app/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;: універсальне посилання&#xA;із цільовим URL у шляху та обов&amp;rsquo;язковим &lt;code&gt;ref&lt;/code&gt;. Здогадка з власною схемою на&#xA;кшталт &lt;code&gt;backpack://ul/v1/browse?url=...&lt;/code&gt; не збігається з жодним маршрутом,&#xA;який реєструє застосунок, тож користувач опиняється на сторінці встановлення&#xA;гаманця.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Solflare теж потребує свого універсального посилання:&lt;/strong&gt;&#xA;&lt;code&gt;https://solflare.com/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;, а не голої схеми&#xA;&lt;code&gt;solflare://&lt;/code&gt;. Гола схема може запустити застосунок, не спрямувавши його —&#xA;а це саме те, що «застосунок відкривається, але вкладку із сайтом&#xA;доводиться відкривати вручну».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Обидва параметри мають бути закодовані.&lt;/strong&gt; &lt;code&gt;url&lt;/code&gt; — це повна абсолютна&#xA;адреса dApp, а &lt;code&gt;ref&lt;/code&gt; — origin, який робить запит; кожен проходить через&#xA;&lt;code&gt;encodeURIComponent&lt;/code&gt;. Незакодований &lt;code&gt;?&lt;/code&gt; або &lt;code&gt;&amp;amp;&lt;/code&gt; у цілі псує розбір, і&#xA;гаманець відкривається на своєму головному екрані замість вкладки браузера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Спосіб запуску важить не менше за саме посилання.&lt;/strong&gt; Універсальні посилання&#xA;перемикають застосунки лише під час навігації, якій довіряє операційна&#xA;система — і вони навмисно не роблять нічого, коли їх вставляють в адресний&#xA;рядок, і саме так цілком коректне посилання «не працює» під час тестування.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;задокументовані-формати&#34;&gt;Задокументовані формати&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Phantom: &lt;code&gt;https://phantom.app/ul/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt; — саме тут без&#xA;&lt;code&gt;/v1&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Solflare: &lt;code&gt;https://solflare.com/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;Backpack: &lt;code&gt;https://backpack.app/ul/v1/browse/&amp;lt;url&amp;gt;?ref=&amp;lt;ref&amp;gt;&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Один шаблон покриває всі три:&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;const WALLET_BROWSE = {&#xA;  phantom: (url, ref) =&amp;gt;&#xA;    `https://phantom.app/ul/browse/${url}?ref=${ref}`,&#xA;  solflare: (url, ref) =&amp;gt;&#xA;    `https://solflare.com/ul/v1/browse/${url}?ref=${ref}`,&#xA;  backpack: (url, ref) =&amp;gt;&#xA;    `https://backpack.app/ul/v1/browse/${url}?ref=${ref}`,&#xA;};&#xA;&#xA;function walletBrowseLink(&#xA;  walletName,&#xA;  targetUrl = window.location.href,&#xA;) {&#xA;  const build = WALLET_BROWSE[walletName.toLowerCase()];&#xA;  if (!build) return null;&#xA;  return build(&#xA;    encodeURIComponent(targetUrl),&#xA;    encodeURIComponent(window.location.origin),&#xA;  );&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;як-запустити-посилання-щоб-ios-та-android-його-прийняли&#34;&gt;Як запустити посилання, щоб iOS та Android його прийняли&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Рендерте справжній якір, обчислений заздалегідь.&lt;/strong&gt; Звичайний&#xA;&lt;code&gt;&amp;lt;a href={walletBrowseLink(&#39;phantom&#39;)}&amp;gt;&lt;/code&gt; — найнадійніший спосіб запуску на&#xA;обох платформах.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Якщо це має бути програмно&lt;/strong&gt;, присвоюйте &lt;code&gt;window.location.href&lt;/code&gt; синхронно&#xA;всередині обробника натискання — без &lt;code&gt;await&lt;/code&gt;, без &lt;code&gt;fetch&lt;/code&gt;, без &lt;code&gt;setTimeout&lt;/code&gt;&#xA;перед цим. Після асинхронної роботи контекст жесту втрачено, і iOS&#xA;відкочується до вебсайту гаманця. Ніколи не використовуйте &lt;code&gt;window.open&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ніколи не тестуйте вставлянням в адресний рядок.&lt;/strong&gt; Універсальні посилання&#xA;навмисно там не спрацьовують; тестуйте посиланням, на яке натискають, або&#xA;QR-кодом, який сканує камера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Зважайте на webview месенджерів.&lt;/strong&gt; Відкриті у вбудованому браузері&#xA;Telegram або Instagram, універсальні посилання часто просто поглинаються, і&#xA;натомість завантажується звичайний вебсайт гаманця. Визначення за&#xA;user-agent — у кращому разі евристика, тож дайте користувачам ще й видимий&#xA;запасний вихід: «відкрийте в Safari чи Chrome, а тоді під&amp;rsquo;єднайтеся».&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;ґрунтовніше-виправлення-на-android&#34;&gt;Ґрунтовніше виправлення на Android&lt;/h2&gt;&#xA;&#xA;&lt;p&gt;Саморобні deeplinks — це історія про iOS. На Android Mobile Wallet Adapter від&#xA;Solana Mobile дає dApp, що працює в мобільному браузері, під&amp;rsquo;єднатися прямо до&#xA;встановленого застосунку гаманця, узагалі без гаку через вбудований браузер.&#xA;Свіжі версії &lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt; реєструють мобільний адаптер&#xA;автоматично, тож оновлення пакетів wallet-adapter може полагодити Android саме&#xA;собою. Цільова архітектура: Mobile Wallet Adapter на Android, універсальні&#xA;browse-посилання на iOS, де Apple не дозволяє нічого рівноцінного.&lt;/p&gt;&#xA;&lt;h2 id=&#34;перевірка-на-пристрої&#34;&gt;Перевірка на пристрої&lt;/h2&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Справжній пристрій, встановлений гаманець, посилання відкрито із системного&#xA;браузера — не з месенджера.&lt;/li&gt;&#xA;&lt;li&gt;Натисніть відрендерене посилання або відскануйте QR-код; ніколи не&#xA;вставляйте в адресний рядок.&lt;/li&gt;&#xA;&lt;li&gt;Переконайтеся, що гаманець відкривається і dApp завантажується у вкладці&#xA;його вбудованого браузера — саме друга половина і ламається.&lt;/li&gt;&#xA;&lt;li&gt;Повторіть без встановленого гаманця: універсальне посилання має деградувати&#xA;до вебсайту гаманця. Якщо ця сторінка з&amp;rsquo;являється, коли застосунок&#xA;встановлено, — посилання або спосіб запуску все ще неправильні.&lt;/li&gt;&#xA;&lt;li&gt;Потім перевірте шлях через месенджер і додайте підказку «відкрийте у&#xA;браузері», якщо там не спрацьовує.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;джерела&#34;&gt;Джерела&lt;/h2&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.phantom.com/phantom-deeplinks/deeplinks-ios-and-android&#34;&gt;Phantom: deeplinks на iOS та Android&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.solflare.com/solflare/technical/deeplinks/other-methods/browse&#34;&gt;Solflare: Browse-deeplink&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.backpack.app/deeplinks/other-methods/browse&#34;&gt;Backpack: Browse-deeplink&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://docs.solanamobile.com/mobile-wallet-adapter/mobile-apps&#34;&gt;Solana Mobile: Mobile Wallet Adapter&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</content>
  </entry>
</feed>
