CN Wszystkie projekty

TuMedytuj

Medytacja pisana pod jedną sytuację.

TuMedytuj tworzy medytację, tekst i głos, pod sytuację, w której ktoś jest właśnie teraz. Nie kolejne ogólne nagranie z YouTube. To pierwsze takie narzędzie po polsku, na jakie trafiłem.

Zbudowałem je sam w około dwa tygodnie, od 7 do 19 września 2026. To jednostronicowa aplikacja z wbudowanym generatorem, świadomie bez kont użytkowników i osobnego zaplecza SaaS. Działa pod własną domeną, tumedytuj.pl.

Karta generatora TuMedytuj: pytanie Z czym się dzisiaj mierzysz, pole na własne słowa, podpowiedzi takie jak Nie mogę zasnąć i Presja w pracy, wybór długości sesji z odblokowanym tylko wariantem 5 minut, przycisk Wygeneruj medytację i licznik Pozostało Ci 5 z 5 w tym miesiącu
Generator na żywej stronie, 6.10.2026. Dłuższe sesje są zablokowane, bo należą do pakietów doładowań, które jeszcze nie są w sprzedaży.
Rola
Product design i front-end
Czas
Około dwóch tygodni
Stack
Next.js, Claude, ElevenLabs
Status
Działa na tumedytuj.pl

Punkt wyjścia

Koszt jednej sesji nie jest stały.

To zmieniło wszystko, zanim zaprojektowałem pierwszy ekran.

Nie zaczynałem od interfejsu, tylko od pytania, które okazało się najważniejszą decyzją w całym projekcie: ile właściwie kosztuje powstanie jednej medytacji i czy da się to pokryć modelem, który stosują wszyscy w tej kategorii.

Konkurencja działa na czystej subskrypcji: stała opłata miesięczna za dostęp. Na starcie poszedłem tą samą drogą, dopóki nie policzyłem, ile naprawdę kosztuje jedna medytacja.

Koszt syntezy głosu rośnie liniowo z długością nagrania, bo ElevenLabs rozlicza się od znaku. Przy modelu „subskrypcja = nielimitowany dostęp” nie da się z góry policzyć marży, bo garstka bardzo aktywnych użytkowników potrafi zjeść zysk wypracowany przez resztę.

Przy silnie zmiennym koszcie jednego użycia około 8% użytkowników potrafi odpowiadać za około 61% kosztów w modelu subskrypcyjnym.

Znalazłem tekst Freemiusa z tego samego miesiąca, który to potwierdzał. To nie było „sprzedaż mogłaby być lepsza”. To był konkretny, policzalny koszt, który musiał zdecydować o architekturze produktu, zanim zacząłem cokolwiek projektować wizualnie.

Cennik z 8.09.2026: plan Za darmo i ciemna karta Pro za 19 zł miesięcznie z etykietą Wkrótce, w niej Dłuższe sesje 10 i 15 minut, Nielimitowane medytacje oraz Zapisywanie i własna biblioteka
Powiększ kadr
8.09.2026, przed decyzją Pro za 19 zł miesięcznie

„Nielimitowane medytacje” za stałą cenę, przy koszcie, który rośnie z każdą minutą nagrania.

Cennik dziś: plan Za darmo, nagłówek Doładowania, nie subskrypcja, pasek 5 min = 1 jednostka, 10 min = 2, 15 min = 3 oraz trzy pakiety Pierwszy krok 19 zł, Rytuał 45 zł i Codzienność 79 zł
Powiększ kadr
Dziś na tumedytuj.pl Doładowania w jednostkach

5 minut to jedna jednostka, 10 minut dwie, 15 minut trzy. Krótsza medytacja zużywa mniej, dłuższa więcej.

Lewy kadr to strona z commita d722498 (8.09.2026, 23:29), odtworzona z historii gita i uruchomiona lokalnie. Prawy to żywa strona z 6.10.2026. Płatności nie są jeszcze uruchomione w żadnej wersji.

Zmieniłem model na doładowania. W trakcie budowy poprawiłem go jeszcze raz: zamiast liczyć każdą medytację tak samo, przeszedłem na jednostki zależne od długości nagrania. Ta jedna decyzja wymusiła zmiany w co najmniej pięciu miejscach strony. Każdą z nich opisałem osobno, z uzasadnieniem, a nie hurtowo.

  1. 01Kontrolka długości sesji
  2. 02Cennik
  3. 03FAQ
  4. 04Hero
  5. 05Mikrocopy formularza

Diagnoza

Strona deklarowała szczerość.

W czterech miejscach jej nie dotrzymywała.

Zanim ktokolwiek to zauważył, sam zrobiłem audyt treści całej strony względem tego, co faktycznie robił kod. Znalazłem cztery rozjazdy naraz. FAQ obiecywało pięć darmowych medytacji miesięcznie „bez gwiazdek i haczyków”, obok nieujawnionego limitu dwóch odsłuchań audio. Hero obiecywał wybór długości sesji, którego darmowy plan nie dawał. Cennik nie wymieniał funkcji, która już istniała. A pakiety płatne reklamowały wybór głosu, który w rzeczywistości był darmowy dla wszystkich. To pozostałość po wycofanym wcześniej planie.

Dla mnie to był poważniejszy problem niż przeciętny wygląd strony. Strona wprost deklarowała przejrzystość jako wartość marki, a w czterech miejscach obiecywała coś, czego produkt nie dawał. Naprawiłem to nie dlatego, że ktoś to zgłosił, tylko dlatego, że deklarowana uczciwość bez regularnego audytu kodu przestaje być prawdą.

Hero

Obietnica wyboru, którego darmowy plan nie dawał

Fakty pod przyciskiem hero przed audytem: 5 / 10 / 15 min, Wybierz długość; 5 medytacji, Miesięcznie za darmo; 0 zł, Bez rejestracji
Przed audytem„5 / 10 / 15 min, Wybierz długość”, choć bez pakietu dostępne było tylko 5 minut.
Fakty pod przyciskiem hero dziś: 5 medytacji, Miesięcznie za darmo; 2 odsłuchania, Głos z podkładem; 0 zł, Bez rejestracji
DziśWybór długości zniknął, na jego miejscu stoi limit: „2 odsłuchania, Głos z podkładem”.
FAQ

„Bez gwiazdek” obok niewymienionego limitu

Pytanie Ile to naprawdę kosztuje przed audytem, odpowiedź: Pięć medytacji miesięcznie nie kosztuje nic. Bez gwiazdek i bez haczyków.
Przed audytemAni słowa o tym, że tylko dwie z pięciu medytacji można odsłuchać.
To samo pytanie dziś, odpowiedź: Pięć medytacji miesięcznie nie kosztuje nic, a dwie z nich odsłuchasz na głos. Bez gwiazdek i bez haczyków.
DziśLimit stoi w tym samym zdaniu co obietnica, więc „bez gwiazdek” znowu jest prawdą.
Cennik

Darmowy plan bez funkcji, która już istniała

Karta Za darmo przed audytem: cztery punkty, 5 spersonalizowanych medytacji miesięcznie, Technika dobierana pod Twój problem, Sesje 5-minutowe, Bez rejestracji i bez reklam
Przed audytemCztery punkty. Ani odsłuchania na głos, ani podkładów, choć oba już działały.
Karta Za darmo dziś: pięć punktów, w tym 2 z nich odsłuchasz na głos, z podkładem
DziśPiąty punkt mówi i o funkcji, i o jej limicie: „2 z nich odsłuchasz na głos, z podkładem”.
Pakiety

Płatna funkcja, która była darmowa

Pakiety przed audytem: pasek Dowolna długość 5, 10 lub 15 minut, Wybór głosu kobiecy lub męski, Bez terminu ważności; pod nim Pierwszy krok, Rytuał i Codzienność liczone w medytacjach
Przed audytem„Wybór głosu: kobiecy lub męski” jako zaleta pakietu, choć głos wybierał każdy, także za darmo. Pozostałość po planie Pro.
Pakiety dziś: pasek 5 min = 1 jednostka, 10 min = 2, 15 min = 3, Każda medytacja z odsłuchaniem na głos, Bez terminu ważności; pod nim te same trzy pakiety liczone w jednostkach
DziśPasek mówi o tym, co pakiet naprawdę dokłada: odsłuchanie każdej medytacji. Ceny są w jednostkach, nie w medytacjach.

Stan „przed audytem” to strona z commita 68488d2 (9.09.2026, 13:40), odtworzona z historii gita. Wszystkie cztery rozjazdy zamknąłem jednym commitem 9.09 o 14:21, razem z przejściem na jednostki.

Uczciwość jako cecha produktu, nie hasło na stronie.

Z tej diagnozy wyciągnąłem zasadę, do której wracałem przy każdej kolejnej decyzji: uczciwość ma być czymś, co produkt robi, nie czymś, co o sobie mówi. Odrzuciłem fabrykowany social proof: zero testimoniali, logotypów mediów i wymyślonych liczb użytkowników. Dla małego produktu autentyczność budowałem inaczej niż standardowym zestawem wzorców na wzrost.

Pasek wspólnych cech nad cennikiem miał najpierw kafel z wypełnionym tłem. Odrzuciłem tę wersję, bo rozpoznałem w niej dokładnie ten szablonowy wygląd AI-SaaS, którego unikać każe mój własny design-system.md, i zostawiłem cienkie linie, w których utrzymana jest reszta strony.

  1. Zgoda na analitykę

    Baner, który naprawdę pyta

    Przy odmowie skrypt Vercel Analytics w ogóle się nie montuje, nie tylko przestaje zapisywać dane. Oba przyciski, zgody i odmowy, mają tę samą wagę wizualną, bo mniejszy albo ukryty przycisk odmowy nazwałem wprost ciemnym wzorcem, a nie kwestią hierarchii.

    Baner Bez ciasteczek: Zbieram anonimowe statystyki odwiedzin, żeby wiedzieć, czy ta strona komuś służy. Dwa przyciski tej samej szerokości: W porządku i Wolę nie
  2. Długość sesji

    Zdanie zamiast pytania

    Kontrolkę długości sesji opisałem zdaniem oznajmującym „Twoja sesja potrwa”, a nie pytaniem „Ile masz czasu?”, bo pytanie, na które produkt nie może uczciwie odpowiedzieć wyborem, czyta się jak obietnica.

    Kontrolka przed zmianą: nagłówek Ile masz czasu?, aktywne 5 minut, 10 i 15 minut z kłódką
    Wcześniej
    Ta sama kontrolka dziś: nagłówek Twoja sesja potrwa, aktywne 5 minut, 10 i 15 minut z kłódką
    Dziś
  3. Wybór głosu

    Limit stoi tam, gdzie zapada decyzja

    Przy wyborze głosu strona mówi, ile odsłuchań zostało i że wybór jest wiążący, zanim ktoś kliknie. To ten sam limit, którego przed audytem brakowało w FAQ.

    Wybór Głos kobiecy lub Głos męski, link Posłuchaj próbki tego głosu, przycisk Odsłuchaj na głos i dopisek: Pozostało Ci 1 z 2 odsłuchań w tym miesiącu. Wybrany głos zostanie już przy tej medytacji, więc posłuchaj próbki, zanim zdecydujesz.

Metoda

Zmierz, nie zgaduj.

To samo zdanie wracało przy każdej decyzji.

Ten wzorzec widać w całym changelogu, nie tylko przy głosie czy cenniku. Kontrast koloru wyróżnionej kolumny w tabeli porównawczej zmierzyłem i wyszło 1,07:1, na granicy progu widzenia. Poprawiłem go do 1,32:1 nowym tokenem koloru, nie zmianą przezroczystości.

Dekoracje graficzne w tle sekcji miały stałą szerokość w pikselach, więc na węższych ekranach prawie znikały, a na szerszych nachodziły na tekst nawet o 30 pikseli. Zamieniłem je na jednostki względne, żeby widoczna część dekoracji była stała niezależnie od szerokości okna.

Kontrast wyróżnionej kolumny
1,07 → 1,32:1
Zmierzony wobec tła karty, przed i po nowym tokenie.
Nakładanie dekoracji na tekst
30 → 0 px
Sprawdzone przy 1280, 1440 i 1920 px szerokości okna.
Tabela porównawcza przed zmianą: kolumna Twoja medytacja ma tło prawie identyczne jak reszta karty
Kontrast 1,07:1Zieleń rozcieńczona do 40% krycia. Wyróżniona kolumna prawie nie odstaje od reszty.
Tabela porównawcza dziś: kolumna Twoja medytacja ma wyraźne zielone tło, wiersze mają znaczniki kreski i ptaszka
Kontrast 1,32:1Osobny kolor zamiast rozcieńczenia. Znaczniki wierszy doszły w kolejnej poprawce tego samego dnia.

Ta sama zasada objęła głos. Kiedy próbowałem przyspieszyć tempo parametrem odtwarzania zamiast syntezy, wynik brzmiał słyszalnie rozciągnięty, mimo że technicznie miał zachowywać wysokość dźwięku. Zapisałem to jako regułę w kodzie:

Tempo należy do syntezy, nie do odtwarzania, nawet jeśli to drugie wydaje się tańsze.

Nie ufałem też pojedynczemu pomiarowi. Przy nietypowych wartościach parametrów mierzyłem kilka razy, bo jeden odstający wynik omal nie trafił do produkcji jako finalna decyzja.

Błąd

Medytacja urywała się tylko na jednym iPhonie.

Testerka zgłosiła, że nagranie kończy się po 20–33 sekundach, mimo że tekst i limit kredytów wskazywały na pełną sesję. Na komputerach i na innych telefonach błąd się nie pojawiał.

Przyczyna okazała się nieoczywista. Każdy plik audio z ElevenLabs niesie nagłówek MP3 deklarujący długość nagrania. Sklejałem segmenty audio bajt po bajcie, więc gotowy plik zaczynał się nagłówkiem opisującym wyłącznie długość pierwszego segmentu, zwykle właśnie 20–33 sekundy zdania otwierającego. Chrome ten nagłówek ignoruje i liczy długość z rozmiaru pliku. Safari mu ufa i kończy odtwarzanie dokładnie tam, gdzie nagłówek każe.

Chrome

Ignoruje nagłówek, liczy długość z rozmiaru pliku i gra do końca. Dlatego na żadnym komputerze nie było błędu.

Safari

Ufa nagłówkowi i kończy odtwarzanie tam, gdzie każe. Na iPhonie medytacja urywała się po pierwszym zdaniu.

Pomiar na sklejce testowej z sesji naprawczej, zapisany w changelogu: 615 ramek w nagłówku, czyli 16,07 s, wobec 46,00 s nagrania. W zgłoszeniu testerki nagranie urwało się po 20 i 33 sekundach.

Napisałem od zera własny parser zdejmujący te nagłówki z każdego segmentu przed sklejeniem. Najwięcej nauczyło mnie jednak coś innego: tę samą zasadę miałem już w kodzie. Plik ciszy wklejanej między segmenty tworzyłem celowo bez żadnych metadanych. Zastosowałem ją do własnego pliku, a nie do plików, które przychodziły z zewnątrz.

Po poprawce testerka zobaczyła w odtwarzaczu pełne 4:47 zamiast kilkudziesięciu sekund. I od razu trafiła na drugie piętro tego samego problemu: w miejscu styku segmentów głos się zacinał, a podkład muzyczny grał dalej w nieskończoność nad ciszą.

Sam podkład grający nad ciszą jest gorszy niż uczciwa informacja o błędzie.

Dodałem czujnik zacięcia, który najpierw próbuje niesłyszalnie przeskoczyć feralny fragment, a po kilku nieudanych próbach zatrzymuje odtwarzanie z komunikatem, zamiast udawać, że wszystko gra dalej. Po obu poprawkach odsłuchałem całą medytację na swoim iPhonie.

Odtwarzacz TuMedytuj: wybrany głos męski, przycisk odtwarzania, pasek postępu 0:00 z 4:30, poniżej podkład z opcjami Przestrzeń, Deszcz, Fale, Bez muzyki i suwak głośności tła
Własny odtwarzacz z podkładem. To w nim głos i muzyka rozjeżdżały się na styku segmentów.

Rezultat

Co jest gotowe, a co świadomie odłożyłem.

Działa cały generator: opis sytuacji użytkownika, tekst medytacji, głos do wyboru z próbką przed decyzją, opcjonalny podkład dobierany do nastroju i własny odtwarzacz zgodny z resztą systemu wizualnego.

Strona ma też ścieżkę bezpieczeństwa. Jeśli to, co wpisał użytkownik, wskazuje na sytuację kryzysową, pokazuję osobny, spokojny ekran z klikalnymi numerami wsparcia zamiast kontynuować medytację.

  1. Własne słowa zamiast listy kategorii

    Ktoś opisuje, z czym się dziś mierzy, a generator dobiera do tego technikę.

    Karta generatora z wpisanym tekstem Nie mogę zasnąć i czuję pustkę, przycisk w stanie ładowania: Dobieram technikę dopasowaną do Twojej sytuacji
  2. Tekst napisany pod tę jedną sytuację

    Medytacja odpowiada na wpis: łóżko, kołdra, sen. Pionowe kreski w tekście to pauzy, które słychać potem w nagraniu.

    Gotowa medytacja: Możesz teraz pozwolić powiekom opaść, jeśli jeszcze tego nie zrobiłaś czy zrobiłeś. Wystarczy, że tu jesteś, w łóżku, otulony czy otulona kołdrą. Kolejne akapity oddechu oddzielone pionowymi kreskami
  3. Głos z próbką, podkład i odtwarzacz

    Wybór głosu z ujawnionym limitem pokazałem przy audycie, a odtwarzacz przy błędzie z iPhonem.

Przez cały okres budowy i testów powstało 1,83 godziny nagrań za 35,6 tys. kredytów ElevenLabs. To główny koszt projektu, bo tekst pisany przez Claude kosztował grosze. Statystyki odwiedzin pokazały 26 osób, ale tylko te, które kliknęły zgodę. Reszta, tak jak to zaprojektowałem, nie zostawiła śladu.

Nagrania
1,83 h
Cały okres budowy i testów, z moimi próbami włącznie.
Koszt głosu
35,6 tys.
Kredytów ElevenLabs, panel z 5.10.2026.
Testujący
~10
Rodzina i znajomi. Liczba z pamięci, bez pomiaru.
Odwiedzający
26
Tylko ci, którzy zgodzili się na statystyki.
Świadomie poza MVP

Konta użytkowników i prawdziwy checkout zostawiłem poza MVP, bo wymagają osobnej infrastruktury płatniczej, którą chcę wdrożyć dopiero z realnymi danymi kosztowymi z produkcji, nie z założeń.

Z tego samego powodu indeksacja w wyszukiwarkach jest na razie zablokowana: przypadkowy ruch z Google nie powinien zjadać płatnych kredytów, zanim produkt zarabia. To świadome decyzje, zapisane w dokumentacji z uzasadnieniem, a nie zaniedbania.

Mały design system w Figmie

Do TuMedytuj zbudowałem design system: zmienne, style tekstu, kolory i komponenty z wariantami. Robiłem go w Figmie, a do podpinania zmiennych, stylów, kolorów i tekstów używałem AI.

Nazwy i wartości tokenów zgadzają się z kodem strony. Cennik na stronie Demo składa się z tych samych komponentów, z tymi samymi pakietami i cenami co na tumedytuj.pl.

Zobacz plik w Figmie

Przy każdej sekcji pliku dopisałem, dlaczego zrobiłem to tak, a nie inaczej. Trzy przykłady:

  • Kolor

    Zaczęłem od pytania, kto tu przychodzi: ktoś wieczorem, zmęczony, kto chce na chwilę ciszy. Dlatego główną barwą jest głęboka zieleń, a nie niebieski, który kojarzy się z bankiem albo aplikacją do pracy.

  • Pismo

    Wiem, że szeryfowy nagłówek z bezszeryfową treścią to dziś układ kojarzony ze stronami robionymi przez AI. Zostawiłem go, bo tu ma konkretną robotę.

  • Karty

    Cień dostaje tylko treść główna, ramkę treść drugorzędna, a obu naraz nigdy. Gdyby wszystko miało cień, nic by się nie wyróżniało.

Strona Demo w Figmie: nagłówek Zacznij za darmo i trzy karty cennika, Za darmo z cieniem, Pierwszy krok z ramką i Rytuał na ciemnym tle
DemoCennik złożony z instancji komponentów: Card, Badge i Button.
Strona komponentu Card z opisem Dlaczego tak i trzema wariantami: Raised z cieniem i bez ramki, Quiet z ramką i bez cienia, Dark na ciemnym tle
CardTrzy warianty z opisem, dlaczego tak: promień 28 px zawsze, a ramka i cień nigdy na jednej karcie.

Wniosek

Najwięcej zostaje mi z metody, nie z samej aplikacji.

Kod pisałem z pomocą Claude Code. Poza samym interfejsem najwięcej pracy włożyłem w to, żeby projekt nie tracił pamięci. changelog.md i design-system.md aktualizowałem po każdej zmianie, z uzasadnieniem „dlaczego”, nie tylko „co”. Dzięki temu mogłem wracać do projektu po przerwie, a decyzje sprzed kilku dni nie ginęły przy kolejnej sesji. Prowadzenie tej dokumentacji było dla mnie równie ważną pracą co sam interfejs.

To metoda: mierzyć zamiast zgadywać, audytować własne obietnice względem kodu i prowadzić dokumentację na tyle dokładnie, żeby pracować z AI krok po kroku i nie gubić spójności produktu.

Tę metodę mogę powtórzyć w kolejnym projekcie. Interfejs został w tym jednym.


Następne case study

Booking

Niezależny koncept: nocleg na trasie w jednym miejscu, w dwóch wariantach i z planem testu.

Przejdź do projektu

Kontakt

Porozmawiajmy.

Szukam pierwszej pracy jako UX/UI i Product Designer. Jestem dostępny od zaraz.