← всі звіти · index.md

BioGaia Story

Оновлено: 2026-04-15

GitHub

https://github.com/serhiivereschak/biogaia-story (private)

Overview

Веб-застосунок для генерації персоналізованих дитячих казок із брендингом BioGaia. По фото дитини та введеним параметрам генерує 12-сторінкову книжку з ілюстраціями через Gemini AI.

⚠️ Реальна архітектура (відрізняється від планованої!)

Задеплоєно: Firebase Hosting (чистий static frontend — без backend!)

[Браузер клієнта]
  → script.js викликає Gemini API НАПРЯМУ (key захардкожений у JS!)
    → gemini-2.5-pro: аналіз фото → character_desc
    → gemini-2.5-pro: генерація тексту → 12 сторінок
    → gemini-2.5-flash-image: генерація зображень × 12
  → db.js: зберігає в IndexedDB (тільки в браузері клієнта)
  → перехід на book.html

[app.py] — Flask backend існує, але НЕ є частиною продакшн деплою!
         firebase.json виключає app.py з хостингу.

Планована архітектура (в app.py, але не задеплоєна):

[Браузер] → POST /api/generate-story → Flask → Gemini

🔴 Дефекти (Аудит 2026-04-15)

КРИТИЧНО — зупиняє запуск

# Дефект Файл Деталі
1 API ключ у client-side JS script.js:1 GOOGLE_API_KEY = "AIzaSyBNd..." — будь-який користувач може відкрити DevTools і вкрасти ключ
2 Другий API ключ у book.js book.js:55 GOOGLE_API_KEY = "AIzaSyBNd..." — той самий ключ, дублюється
3 Немає rate limiting Будь-хто може відкрити сторінку і зробити 1000 запитів — рахунок на сотні доларів

ВАЖЛИВО — впливає на UX клієнта

# Дефект Файл Деталі
4 Помилка одного зображення = крах всього script.js:113 throw imgError — якщо 1 з 12 ілюстрацій не згенерується, вся казка втрачається
5 Казка тільки в IndexedDB db.js Якщо клієнт відкрив на телефоні, а потім перейшов на ноутбук — казки нема. Не можна поділитися посиланням
6 gemini-2.5-flash-image endpoint script.js:100 Модель gemini-2.5-flash-image — нестабільна/experimental, може повертати 404
7 Немає fallback при невдалій генерації script.js Якщо AI повертає не-JSON — сирий текст моделі показується юзеру
8 13 сторінок замість 12 script.js Іноді модель генерує 13 сторінок (porушення prompt) — UI адаптується але dots некоректно
9 Непослідовна зовнішність дитини Персонаж на різних сторінках виглядає по-різному — imagePrompt не містить "seed" або reference image

ДРІБНИЦІ

# Дефект Деталі
10 Тестові файли в репо test_rate_limit.html/js/py, test_seed.html — виключені з Firebase, але мусорять репо
11 Неузгодженість моделей app.py використовує gemini-1.5, script.js — gemini-2.5
12 Немає валідації input Поле "Ім'я дитини" — немає обмежень довжини/символів

✅ Що працює


🛠️ Пріоритетний план виправлень

Фаза 1: ОБОВ'ЯЗКОВО до першого клієнта

  1. Перегенерувати API ключ у Google AI Studio (старий скомпрометований публічним git)
  2. Перенести API виклики на backend (Cloud Function або простий VPS endpoint) — ключ ніколи не повинен бути в JS
  3. Rate limiting: обмежити 3-5 запитів на день з однієї IP або прив'язати до email клієнта

Фаза 2: Покращення UX

  1. Fallback для провалених зображень (показати placeholder замість краш)
  2. Зберігати казку на сервері (щоб можна було поділитися посиланням)
  3. Прибрати тестові файли з репо

Stack (фактичний)

Key Files

Файл Опис
script.js Головна логіка — форма, виклики Gemini, зберігання
book.js Рендер сторінок книжки, навігація
db.js IndexedDB обгортка (saveStory/loadStory)
index.html Форма вводу
book.html Перегляд готової казки
app.py Flask backend (не в продакшн деплої)
firebase.json Налаштування Firebase Hosting

Бренд (продукт)