# Gift Planning App – MVP Specification **Project Name:** Gift Planner **Created:** December 26, 2025 **Status:** Pre-development / Discovery Phase --- ## 1. Project Vision & Goals ### Business Goal Aplikacja wspomaga planowanie i śledzenie prezentów na dowolne okazje (święta, urodziny, rocznice), automatyzując zarządzanie budżetem, listami osób i śledzeniem cen. ### Success Metrics (do doprecyzowania) - Liczba zarejestrowanych userów - % userów, którzy ukończy workflow od okazji do budżetu - Engagement z AI recommendations - Średni czas planowania okazji ### Ograniczenia na start - Budżet: TBD - Deadline MVP: TBD - Zespół: TBD - Geograficznie: Polska (Ceneo integration) --- ## 2. Core Domain – MVP Scope ### User & Authentication - [ ] Rejestracja / logowanie (email + hasło) - [ ] Profil usera (opcjonalnie: foto, preferencje powiadomień) - [ ] **Bez social logins na MVP** - [ ] Brak współdzielenia list (single-user na MVP) ### Globalna Lista Osób (User Resource) Przypisana do usera, reużywalna między okazjami. **Pola:** - `id`, `userId` - `name` (imię/pseudonim) - `relation` (np. matka, przyjaciel, partner – dla kontekstu AI) - `age` (opcjonalnie, dla AI recommendations) - `interests` (notatki/tagi: sport, gaming, moda itp.) - `notes` (dowolne notatki) - `createdAt`, `updatedAt` **Operacje:** - CRUD na osobach - Lista osób dla danego usera - Search/filter po nazwie --- ### Okazja (Occasion) Kontener dla prezentów i budżetu w konkretnym kontekście czasowym. **Pola:** - `id`, `userId` - `title` (np. "Święta 2025", "Urodziny Anny") - `description` (opcjonalnie) - `date` (przybliżona data okazji) - `totalBudget` (opcjonalnie, całkowity budżet na okazję) - `status` (draft, planning, shopping, done) - `createdAt`, `updatedAt` **Operacje:** - CRUD na okazjach - Lista okazji dla danego usera - Filtry: aktywne, przeszłe, po dacie --- ### Powiązanie Osoba ↔ Okazja Tablica łączy osoby z okazjami (wiele-do-wielu). **Pola:** - `id`, `occasionId`, `personId` - `budgetPerPerson` (opcjonalnie, Budget przydzielony dla tej osoby na tę okazję) - `notes` (opcjonalnie, specyficzne notatki dla tej osoby w ramach tej okazji) - `createdAt` **Operacje:** - Dodaj osoby do okazji (można masowo) - Usuń osobę z okazji - Edytuj budżet per osoba --- ### Prezent (Gift) Konkretny prezent przypisany do osoby w ramach okazji. **Pola:** - `id`, `occasionId`, `personId` - `title` (nazwa prezentu) - `status` (idea, selected, bought, wrapped, given – lub podobne state machine) - `price` (cena szacunkowa lub aktualna z Ceneo) - `budget` (z czego się liczy: czy wlicza się w budżet osoby?) - `description` (opcjonalnie, szczegóły) - `url` (opcjonalnie, link do produktu/sklepu) - `createdAt`, `updatedAt` **Operacje:** - CRUD na prezentach - Change status prezentu - Lista prezentów per osoba - Lista prezentów per okazja (agregat) --- ### Budżet & Postęp (Occasion Analytics) Obliczone **automatycznie** na podstawie prezentów i okazji. **Per Okazja:** - Całkowity budżet (suma `totalBudget` lub suma `budgetPerPerson` dla wszystkich osób) - Wydane dotychczas (suma `price` prezentów ze statusem ≥ "selected") - Pozostały budżet - % wykorzystania budżetu - Liczba osób - Liczba prezentów (total, ready/wrapped, pending) **UI Representation:** - Progress bar: wydane / budżet - Liczniki: "3 z 5 osób gotowych", "12 z 15 prezentów" - Alert, jeśli przekraczamy budżet --- ## 3. Secondary Features – Phase 2 (Post-MVP) ### Price Tracking via Ceneo **Architecture:** - User dodaje `url` do prezentu (dowolny link, np. ceneo.pl/...) - Backend: cron job (raz dziennie lub częściej) + manualne "refresh" przez UI - Pobieranie aktualnej ceny z API Ceneo / scrapingiem (Apify) - Zapis snapshotu ceny do tabeli `PriceSnapshot(giftId, price, timestamp, source)` **Pola Gift (extended):** - `currentPrice` (najniższa cena z ostatniego snapshotu) - `priceHistory` (relacja do `PriceSnapshot`) - `priceAlert` (boolean: czy śledzić zmiany cen?) - `priceAlertThreshold` (opcjonalnie: powiadom, gdy spadnie poniżej X) **UI Features:** - Mini-sparkline / mini-wykres ostatnich 30 dni cen - Badge: "Najtaniej w 2 tygodniach" lub "Drożej o X%" od średniej - Alert: "Cena spadła poniżej progu – dobry moment!" **Powiadomienia (Phase 2):** - Email/push alert, gdy cena spadnie poniżej threshold - Reminder: "Zbliżają się święta – ceny mogą wzrosnąć" - Scheduled reminder: "Sprawdzaj ceny tego prezentu co 3 dni" --- ### AI Gift Recommendations (Phase 2) **Use Case:** User przychodzi na okazję, widzi osobę w liście, kliknie "Suggest Gifts" → AI generuje 5–10 propozycji z uzasadnieniami. **Input Context (AI):** - Profil osoby: wiek, zainteresowania, relacja - Okazja: typ, budżet per osoba, pozostały budżet na całą okazję - Historia: jakie prezenty już kupił/planuje dla tej osoby w historii (unikaj duplikatów) - Unikalność: weź pod uwagę, jakie prezenty planuje dla innych osób (różnorodność) **Output:** - Lista propozycji: [{ title, category, priceRange, reason, matchScore }] - Reason: "Lubisz gaming, a wiek sugeruje..." itp. - Link do szukania: łatwe przejście do Ceneo/Google Shopping **Implementacja:** - LLM (OpenAI API / local Ollama / inne) - Prompt engineering: struktura context + constraints (budżet, unikalne przedmioty) - User ręcznie decyduje, co dodać (zero auto-dodawania, pełna kontrola) --- ## 4. Architektura Techniczna (High Level) ### Tech Stack (Proposed) - **Frontend:** React 19 + Next.js (App Router) - Server Components dla list/agregacji - Client Components dla interaktywnych formularzy - TanStack Query do synchronizacji danych - **Backend:** Node.js / Next.js API Routes lub oddzielny backend (Express/NestJS) - REST API lub GraphQL (tbd) - Autentykacja: JWT / session-based - **Database:** PostgreSQL (+ Prisma ORM) - Wersjonowanie: migrations - **External Services:** - Ceneo API / Apify scraper (Phase 2) - OpenAI API lub self-hosted LLM (Phase 2) - Email service (e.g., SendGrid, Resend) dla alertów (Phase 2) - **Deployment:** TBD (Vercel, self-hosted, AWS, etc.) --- ### Database Schema (Sketch) ``` User ├── id (PK) ├── email (UNIQUE) ├── password_hash ├── created_at └── updated_at Person ├── id (PK) ├── user_id (FK) ├── name ├── relation ├── age ├── interests (TEXT / JSON) ├── notes ├── created_at ├── updated_at Occasion ├── id (PK) ├── user_id (FK) ├── title ├── description ├── date ├── total_budget ├── status (draft | planning | shopping | done) ├── created_at ├── updated_at OccasionPerson (M2M) ├── id (PK) ├── occasion_id (FK) ├── person_id (FK) ├── budget_per_person ├── notes ├── created_at Gift ├── id (PK) ├── occasion_id (FK) ├── person_id (FK) ├── title ├── status (idea | selected | bought | wrapped | given) ├── price ├── description ├── url ├── price_alert (BOOLEAN) ├── price_alert_threshold (DECIMAL, optional) ├── created_at ├── updated_at PriceSnapshot (Phase 2) ├── id (PK) ├── gift_id (FK) ├── price (DECIMAL) ├── source (e.g., "ceneo", "direct") ├── timestamp ├── created_at AIRecommendation (Phase 2, optional logging) ├── id (PK) ├── occasion_id (FK) ├── person_id (FK) ├── prompt_context (JSON) ├── result (JSON - lista propozycji) ├── created_at ``` --- ### API Endpoints (MVP, Sketch) #### Auth - `POST /api/auth/register` → register user - `POST /api/auth/login` → login user - `POST /api/auth/logout` → logout #### Persons - `GET /api/persons` → list all persons for logged user - `POST /api/persons` → create person - `PUT /api/persons/:id` → update person - `DELETE /api/persons/:id` → delete person #### Occasions - `GET /api/occasions` → list occasions for logged user - `POST /api/occasions` → create occasion - `PUT /api/occasions/:id` → update occasion - `DELETE /api/occasions/:id` → delete occasion - `GET /api/occasions/:id` → get occasion with full context #### OccasionPerson (Managing persons in occasion) - `POST /api/occasions/:id/persons` → add person(s) to occasion - `DELETE /api/occasions/:id/persons/:personId` → remove person - `PUT /api/occasions/:id/persons/:personId` → update budget_per_person #### Gifts - `GET /api/occasions/:id/gifts` → list gifts for occasion - `POST /api/occasions/:id/gifts` → create gift for person - `PUT /api/gifts/:id` → update gift (title, status, price, url, etc.) - `DELETE /api/gifts/:id` → delete gift #### Occasion Analytics (computed read-only) - `GET /api/occasions/:id/analytics` → budget, postęp, countdowny --- ## 5. UI/UX Flow (MVP) ### Key Views #### 1. Dashboard (Home) - Welcome message - List okazji (karty): aktywne vs archiwalne - Quick stats: ile osób/prezentów do kupienia, budżet całkowity - Shortcuts: "+ New Occasion", "+ Quick Add Gift" #### 2. Okazja Detail (Single Occasion) - Nagłówek: nazwa, data, budżet, progress bar - 2 widoki (tabbed): - **Persons Tab:** lista osób z budżetami, możliwość dodania, usunięcia, edycji budżetu - **Gifts Tab (list view):** wszystkie prezenty dla okazji, szybka edycja statusu/ceny, agregat budżetu #### 3. Osoba Detail (+ Gifts for this Person) - Info: imię, wiek, zainteresowania, notatki - Lista prezentów dla tej osoby (w kontekście aktualnej okazji) - Button: "AI Suggestions" (Phase 2) - Edycja danych osoby #### 4. Gift Detail - Edycja: nazwa, status, cena, URL, opis - Link preview (opcjonalnie: og:image) - Price tracker (Phase 2): mini-chart, alerts - Delete/Archive #### 5. Settings (Simple MVP) - Profil usera - Zmiana hasła - Preferencje powiadomień (Phase 2) - Logout --- ## 6. MVP Definition & Phasing ### MVP = Everything in Section 2 (Core Domain) - ✅ User auth - ✅ Persons management (global reusable list) - ✅ Occasions CRUD - ✅ Connect persons to occasions - ✅ Gifts CRUD + status tracking - ✅ Budget & postęp calculations - ✅ Aggregate gift list per occasion **Timeline:** ~4–8 weeks (team-dependent) ### Phase 2 (Post-MVP, ~4 weeks after) - Price tracking via Ceneo + PriceSnapshot table - Price alerts & notifications (email/push) - AI gift recommendations (LLM integration) ### Phase 3+ (Nice-to-have, Later) - Collaborative lists (share occasion with family) - Analytics: roczne porównania, trendy wydatków - Export to PDF/calendar - Mobile app (native or responsive PWA) - Social: wishlist sharing, gift registry --- ## 7. Key Decisions & Assumptions (To Validate) - [ ] Single-user MVP (no collaboration) – OK? - [ ] Auth method: email/password or OAuth? (assuming email/pwd for MVP) - [ ] Database: PostgreSQL assumption – confirm? - [ ] Ceneo integration: API lub web scraping? (Apify fallback) - [ ] AI model: OpenAI API czy local/self-hosted? (cost/privacy trade-off) - [ ] Monetization: subscription, freemium, ads? (affects feature gating) - [ ] Mobile-first design czy desktop-first? (assuming mobile-responsive on MVP) --- ## 8. Next Steps 1. **Validate domain model** – robi sens struktura User → Occasion → Person → Gift? 2. **Detailed API spec** – co dokładnie zwraca endpoint? 3. **UI wireframes** – sketche ekranów 4. **Phase 1 backlog** – rozbić MVP na user stories + tasking 5. **Tech setup** – inicjalizacja repo, struktura projektu, Prisma schema 6. **First feature cycle** – login/register → Person CRUD → Occasion CRUD --- ## 9. Assumptions & Open Questions ### Business - Czy aplikacja ma być darmowa czy z opcjami premium? - Target audience: Polska czy szerzej? - Launch timeline? ### Technical - Czy self-hosted czy cloud (Vercel, Railway)? - Rate limits dla Ceneo API czy backup plan? - Jak long-term archivizować stare okazje? ### Product - Czy dark mode na MVP? - Czy offline support (PWA)? - Czy mobile app native czy Web + PWA? --- **Document Version:** 1.0 **Last Updated:** December 26, 2025 **Status:** Awaiting validation & feedback