Займаючись вебпрограмуванням уже досить давно, я інколи думав про те, щоб створити власний нативний застосунок для смартфона. Але було два нюанси: брак знань із мобільної розробки та відсутність проблеми, яку мав би розв’язувати застосунок.
Звісно, ШІ допоміг із технічною частиною розробки, а проблема, яку мав розв’язувати застосунок, знайшлася сама собою. Я вже давно, а саме з 2020 року, користуюся застосунками для аналізу особистих фінансів. За цей час я добре зрозумів, які обмеження мають наявні на ринку рішення. Особливо помітними вони стали, коли я почав цікавитися інвестиціями.
Тож я вирішив створити власний застосунок для обліку особистих фінансів з урахуванням набутого досвіду та потреби вести облік інвестицій.
Я обрав iOS як платформу для застосунку з двох простих причин: користуюся iPhone, а на iOS, на мою думку, кращі можливості для монетизації.
Щодо технічного стеку вибір був між React Native і Swift. Оскільки я маю понад 12 років досвіду роботи з React, логічніше було б обрати React Native, адже це пришвидшило б розробку. Однак через нативність я обрав Swift. Пізніше я все ж трохи пошкодував про це, коли кілька днів боровся з проблемами продуктивності, адже мало знав про оптимізацію у Swift.
На роль помічників я обрав ChatGPT і Claude Code. Обидві підписки коштували по 20 доларів. Codex і Claude Code я використовував через їхні застосунки, бо це банально зручніше, ніж термінал чи вбудовані в IDE чат-системи.
Далі я зайнявся найважливішим: разом із «помічниками» склав список функцій і сторінок, які мала містити перша версія застосунку. На той момент я вже знав, що саме мені потрібно. На основі досвіду користування іншими застосунками мені вдалося поєднати те, чим я користувався щодня, із тим, чого мені бракувало в наявних рішеннях.
У своєму застосунку я зосередився на розв’язанні простої проблеми. Зазвичай застосунки поділяються на ті, що призначені для обліку особистих фінансів і бюджетування, та ті, що створені для контролю інвестиційного портфеля. Ці напрями існують окремо, оскільки кожен із них стає дуже масштабним, якщо заглиблюватися в деталі. Я вирішив поєднати обидва напрями, але залишити аналітику інвестицій спрощеною — настільки, щоб розуміти поточний стан портфеля та бачити, як він змінювався з часом, але без надмірної деталізації.
Роботу над дизайном я почав з іконки застосунку. Спочатку пробував генерувати її за допомогою ШІ через Gemini, ChatGPT і Figma Make. Найкращі результати були у Figma Make, але в безкоштовній версії кількість запитів обмежена. У підсумку я створив власну іконку з нуля у Figma, використавши векторну графіку, хоча під час пошуку ідеї все ж надихався результатами ШІ.
Дизайн екранів мені не довелося довго промальовувати. Оскільки це фінансовий застосунок, я вирішив максимально використовувати стандартні UI-компоненти Apple. Тому не створював у Figma окремий макет для кожної сторінки. Натомість я давав ШІ запити з дуже конкретним описом того, що хотів бачити в певній секції чи на сторінці. Також додавав примітку, щоб він використовував стандартні UI-компоненти та елементи SwiftUI.
З-поміж двох агентів я б виділив Claude Code як кращий інструмент для дизайну та побудови інтерфейсів сторінок. Зазвичай із цим він справлявся краще.
Більшість часу я працював, орієнтуючись на ліміти ChatGPT і Claude. Як ви знаєте, у цих тарифних планах є п’ятигодинні й тижневі ліміти токенів. Тож, щоб бути максимально продуктивним, я намагався використовувати всі доступні токени. Кілька разів я вичерпував тижневий ліміт уже посеред тижня. Однак загалом двох підписок вистачало, якщо працювати без надмірного фанатизму та правильно добирати моделі для конкретних завдань.
Я також використовував обидва інструменти ШІ паралельно: давав їм завдання в різних частинах системи, щоб уникнути проблем зі злиттям коду. Класною стратегією була перевірка коду, написаного ChatGPT, за допомогою Claude Code і навпаки. Це допомагало підтримувати високу якість коду й мінімізувати кількість проблем. Оскільки я маю великий досвід у програмуванні, незнання Swift не завадило мені отримати якісний код: я добре знаю основні принципи його написання.
Після реалізації кожної функції чи сторінки я просив «помічників» максимально покривати написаний код тестами. Це дуже допомогло, коли коду стало багато й потрібно було вносити зміни до вже написаних частин.
Завдяки тестам ШІ краще розумів, що й де потрібно змінити, щоб нічого не зламати. Зазвичай я проти громіздких коментарів у коді, але ШІ писав цілі полотна тексту перед методами. Думаю, це також допомагало йому краще розуміти призначення методів і не втрачати контекст.
Корисними були не лише тести, а й запити до ШІ щодо пошуку проблем і покращення коду. Часто я звертався до обох інструментів по черзі. Ось мій стандартний запит:
“Find code duplication, possible code splitting, redundant code, performance problems, security issues, possible code quality improvements. Propose a plan before changing anything.”
Код ми, звісно, писали в Xcode. Для тестування й перевірки я використовував власний iPhone і симулятор. Після завершення розробки я протягом тижня тестував застосунок. Знайшов багато критичних і некритичних помилок, які, звісно, виправив. Чимало помилок стосувалися перекладу. ШІ, звісно, уміє перекладати, але робить це не завжди якісно й іноді пропускає окремі місця. Тому я перевірив усі сторінки в пошуках проблем. Спочатку планував випустити застосунок із підтримкою багатьох мов, але через помилки в перекладах вирішив для початку залишити лише англійську та українську мови.
Щодо монетизації я обрав кілька варіантів покупок у застосунку. Спочатку розділив його на версії Free та Pro, визначив функції, які можна «продавати», і зробив їх доступними лише у версії Pro. Потім додав підписку та можливість одноразової покупки. Усе це легко налаштувати й протестувати локально за допомогою StoreKit. Це одна з переваг використання Swift для розробки застосунку.
Загалом написання коду з нуля тривало до місяця. Я прагнув досягти максимально можливої якості коду. Для фінансового застосунку це особливо важливо, адже потрібно мінімізувати ризик критичних помилок.
Для публікації застосунку Apple вимагає посилання на політику конфіденційності та сторінку підтримки. До того ж кожен застосунок, що себе поважає, має власний вебсайт, тому мій не став винятком. Так, я знаю React і можу легко створити React-застосунок. Але за допомогою ШІ це можна зробити ще легше й швидше 😀. Тож я створив досить простий лендинг із кількома додатковими сторінками.
Далі за допомогою Amazon Route 53, S3 і CloudFront мій новий вебсайт став доступним у всьому світі: https://calmfinance.app. Цей крок виявився для мене досить простим, бо я розуміюся на цій темі. З цікавості я навіть ще трохи попрацював над анімаціями та покращенням дизайну.
Для застосунку також був потрібен канал зворотного зв’язку, тому виникла потреба отримати поштову адресу у власному домені. Трохи розібравшись у темі, я з’ясував, що підписка iCloud дає змогу отримати до трьох адрес. Налаштувавши Route 53 за інструкцією, яку Apple надала під час створення нової поштової адреси, я отримав власну адресу support@calmfinance.app. Великою перевагою є й те, що листи, які надходять на цю нову адресу, фактично потрапляють до моєї особистої скриньки iCloud. Відповіді на них, звісно, надсилаються з нової адреси.
Підготовка застосунку та заповнення всіх даних, необхідних для публікації, зайняли в мене кілька днів. Я користувався ChatGPT і різними відео на YouTube. Загалом усе було не надто зрозуміло, але я якось розібрався.
Зверніть увагу, що налаштування оплат і підписок та додавання інформації про бізнес для отримання виплат — це дві окремі секції процесу публікації.
Я майже тиждень чекав на перевірку застосунку, після чого отримав відмову. Причинами були неправильна URL-адреса сторінки підтримки та відсутність елементів «Privacy Policy» і «Restore Purchase» на екрані покупки.
Процес публікації застосунку вартий окремої статті. Думаю, напишу її пізніше.
Отже, про проблеми.
Незнання різних дрібниць, пов’язаних із розробкою в Xcode, налагодженням iOS-застосунків і публікацією. З іншого боку, це досвід, тож наступного разу я вже все це знатиму.
Недостатнє знання Swift спричинило проблеми з оптимізацією продуктивності, коли функціональність сторінок суттєво зросла. Хоча протягом цього проєкту я навчився налагоджувати iOS-застосунки, оптимізація за допомогою ШІ не завжди давала результат. Мені пощастило, що протягом одного тижня була доступна модель Claude Fable 5. Саме ця модель знайшла й виправила проблему, яку я кілька днів не міг знайти.
Ліміти тарифів ШІ за 20 доларів обмежували мої можливості під час розробки, тому я був змушений перейти на підписку Codex за 100 доларів. Найімовірніше, токени дорожчатимуть, тож до цього варто бути готовими.
Як це часто буває під час розробки чогось нового, початковий план із безліччю функцій у підсумку скорочується до обмеженого набору. Щоб перейти до публікації застосунку, я зменшив кількість підтримуваних мов до двох і відклав реалізацію частини функціоналу на майбутнє. Без цього, певно, ніяк.
Чи подобається мені Swift порівняно з JavaScript? Не те щоб дуже. Мабуть, я вже надто звик до проблем і приколів JS.
Чи сподобався мені досвід публікації та очікування? Не те щоб дуже 😀
Чи варто було витрачати на все це місяць життя? Так, навіть якщо прибуток від продажів буде мінімальним. Ми з родиною та друзями зможемо безкоштовно користуватися класним застосунком.
Розуміння принципів програмування дало мені змогу ставити правильні запитання та формулювати точні команди для ШІ. Я також міг ставити під сумнів дивні рішення ШІ, і це було дуже корисно.
Очікуючи відповіді від Apple понад тиждень, я на власному досвіді відчув, наскільки зросла кількість охочих опублікувати застосунок в App Store. Більшість таких застосунків створено не дуже якісно, а їхні інтерфейси не надто привабливі. Проте це все ж застосунки в App Store, кожен із яких може приносити певний дохід. А якщо створити кілька таких застосунків, то з кожним наступним краще розумієш, як усе працює та як реалізовувати різні ідеї. І це можливо, навіть якщо спочатку зовсім не розумієшся на програмуванні. Тому конкуренція зростає. Але якось воно та й буде 🙂
Отже, ось мій застосунок: https://calmfinance.app.