Skip to content

Repository files navigation

Phoenix — platforma mini-aplikacji

Phoenix to jedna aplikacja-powłoka (super-app), w której mieszkają mini-aplikacje — każda pod własną przestrzenią tras, ze wspólnym logowaniem, profilem i motywem. Ekran główny (/) to launcher z kafelkami zainstalowanych aplikacji podzielonymi na sekcje (Nauka / Narzędzia / Wiara); użytkownik wybiera swoje aplikacje na /aplikacje. Rejestr aplikacji: lib/phoenix/apps.ts — dodanie nowej mini-aplikacji to jeden wpis tam + trasy pod app/(main)/<id>/.

Pierwsza mini-aplikacja to Linguo (/jezyki) — nauka języków po polsku (angielski, hiszpański, rosyjski): fiszki i trener słówek, gramatyka z interaktywnymi lekcjami, czytanie i pisanie oceniane przez AI, tłumaczenie piosenek, słuchanie z lukami (YouTube), gra „łączenie tłumaczeń", prace domowe z panelem admina, kalendarz i streaki, a dla rosyjskiego — wprowadzenie do cyrylicy i ekranowa klawiatura.

Druga mini-aplikacja to Kuźnia (/kuznia) — kreator promptów do budowy kolejnych aplikacji: czat z AI buduje razem z użytkownikiem, wiadomość po wiadomości, gotowy do skopiowania dokument promptu (Markdown), na bieżąco podpowiadając konkretne uzupełnienia i wykrywając sprzeczności/luki w dotychczasowych ustaleniach — z propozycją naprawy jednym kliknięciem. Gotowy prompt wkleja się w nową, osobną sesję czatu, żeby zacząć budowę.

Trzecia mini-aplikacja to Matma (/matma) — pełny kurs + trener zadaniowy + symulator egzaminu przygotowujący do matury rozszerzonej z matematyki (CKE), z celem 80% punktów: interaktywne lekcje (suwaki parametrów wykresów, przeciąganie punktów geometrii, obracalne bryły 3D, rozwiązania krok po kroku z odsłanianiem), bank zadań z czterech źródeł (tematyczne, prawdziwe zadania maturalne CKE, kuratorowane, generowane przez AI) oceniany analitycznym schematem punktowym jak na maturze, diagnoza startowa i adaptacyjna ścieżka nauki per dział, rysik/tablet graficzny (Pointer Events — nacisk, gumka, cofnij/ponów) do zapisu toku rozwiązania, pełne symulacje egzaminu (180 minut, 50 punktów), spersonalizowany harmonogram nauki do dnia matury, trener dowodów i panel nauczyciela.

Czwarta mini-aplikacja to Paragony (/paragony) — paragony, budżet domowy i portfel ETF: skanowanie paragonu ze zdjęcia (Groq, model wizyjny) z ekranem korekty przed zapisem, automatyczna kategoryzacja AI, konta/portfele z saldem per konto, rachunki cykliczne (czynsz, subskrypcje), cele oszczędnościowe z szacowaną datą osiągnięcia, budżet miesięczny plan vs wykonanie z wykresami i drill-downem do listy transakcji; oraz ręczna ewidencja posiadanych ETF-ów z automatycznym pobieraniem i cache'owaniem cen (Stooq dla GPW, FMP dla zagranicznych), wykresem wartości portfela w czasie, CAGR/zmiennością/max drawdown liczonymi z realnych danych (uwzględniając dywidendy) i symulatorem „co jeśli" bez zapisu do bazy.

Piąta mini-aplikacja to Matura z języka (/matura) — przygotowanie do matury z języka obcego (CKE): angielskiego albo hiszpańskiego, poziom podstawowy lub rozszerzony (język i poziom wybierasz na starcie, oba zmienialne w każdej chwili; przełączenie języka niczego nie kasuje — postęp każdego języka czeka tam, gdzie go zostawiłeś). Jeden moduł obsługuje oba języki, bo CKE ustala ten sam format egzaminu dla wszystkich języków obcych nowożytnych — te same cztery części, te same 60/50 punktów, te same kryteria wypowiedzi pisemnej; różni się wyłącznie treść (patrz 0020_matura_language.sql). Struktura odzwierciedla realny egzamin: cztery części — rozumienie ze słuchu, rozumienie tekstów pisanych, znajomość środków językowych, wypowiedź pisemna — każda z osobną wagą punktową (edytowalne przybliżenie, nie oficjalny rozkład CKE) i szacowanym wynikiem na dashboardzie. Wszystkie cztery działy działają już dziś, każdy z biblioteką teorii i bankiem zadań. Teoria to 75 lekcji (matura_lessons, patrz 0021_matura_theory.sql) rozłożonych na oba języki, oba poziomy i wszystkie cztery działy, pogrupowanych na gramatykę, słownictwo i strategię egzaminacyjną. Każda ma własny adres, szacowany czas czytania i znacznik „przerobione". Kolejność lekcji nie jest podręcznikowa, tylko podyktowana tym, na czym Polak realnie traci punkty: po hiszpańsku najpierw ser/estar i por/para, po angielsku wybór czasu i przedimki. Lekcje nie są ścianą tekstu — poza blokami wyjaśniającymi (tabela, oś czasu, formuła, porównanie) mają bloki ćwiczeniowe: uzupełnianie luk z natychmiastowym sprawdzeniem, łączenie w pary, układanie zdania z rozsypanki, tabele odmiany z ukrytymi formami, fiszki i banki zwrotów (lib/grammar/lesson-blocks.ts, komponenty w components/grammar/lesson/). Na 543 bloki treści 168 to ćwiczenia.

Zadania są zorganizowane wokół typów zadań CKE, nie wokół ponumerowanej listy. Wcześniej dział pokazywał „Zadanie 1..N" prosto z banku i każde z nich było jednorazowe — po czterech podejściach dział nie miał już nic do zaoferowania. Egzamin tak nie działa: CKE nie sprawdza „zadania 3", tylko niewielki, stały zestaw typów (słowotwórstwo, parafraza, odmiana czasownika, dobieranie, test wyboru, tłumaczenie fragmentów, prawda/fałsz), które wracają w każdej sesji z inną treścią. Dział listuje więc typy, każdy z licznikiem wykonań i średnią skutecznością, a wejście w typ wydaje zadanie, którego jeszcze nie rozwiązywałeś. Kiedy zapas się kończy, kolejne dopisuje AI (lib/matura/task-stock.ts, lib/matura/generate-tasks.ts) — w tle, przez after() z next/server, więc czekasz na swoje zadanie, a nie na generator. Wyjątkiem jest rozumienie ze słuchu: te zadania wiszą na prawdziwym nagraniu (youtubeVideoId), którego model nie wymyśli, więc ten typ rotuje po kuratorowanym banku zamiast się dogenerowywać. Wypowiedź pisemna chodzi tak samo, tyle że jej typem jest forma (matura_writing_tasks.form_type, lib/matura/writing-stock.ts) — a poziom rozszerzony dostał przy okazji dwie brakujące formy tekstu argumentacyjnego: artykuł publicystyczny i list formalny. Katalog typów wraz z briefami dla generatora: lib/matura/task-types.ts; przypisanie typu do istniejących zadań: 0023_matura_task_types.sql (funkcja matura_infer_task_type plus trigger, żeby ponowne odpalenie seedów nie zgubiło klasyfikacji).

Osobno stoi słownictwo (/matura/slownictwo) — 938 haseł w 15 blokach tematycznych z zakresu podstawy programowej, każde z tłumaczeniem, przykładowym zdaniem, jego tłumaczeniem i notatką o tym, co w danym haśle jest pułapką (kolokacja, rodzaj, fałszywy przyjaciel, składnia typu gustar). Słownictwo celowo NIE jest piątym działem, tylko osobnym wejściem, bo nie jest częścią arkusza — zasila wszystkie cztery. Trenażer dobiera typ pytania do tego, jak dobrze znasz słowo: najpierw rozpoznawanie (fiszka), od trzeciego powtórzenia produkcja (wpisujesz obce słowo z polskiego). Powtórki chodzą na pudełkach Leitnera (lib/matura/vocab-review.ts) z osobną kolejką „na dziś", bo banku tej wielkości nie da się powtarzać liniowo. Znajomość środków językowych: słowotwórstwo, wybór wielokrotny, parafraza jednym wyrazem, parafraza ze słowem kluczowym — oceniane programistycznie (dokładne dopasowanie znormalizowanej odpowiedzi, bez AI). Rozumienie tekstów pisanych: wybór wielokrotny, dopasowanie nagłówków, prawda/fałsz, tekst z lukami zdaniowymi, dopasowanie pytań do fragmentów tekstu — oryginalne teksty w stylu i typach zadań prawdziwych arkuszy CKE, oceniane tak samo programistycznie. Rozumienie ze słuchu: prawdziwe, publicznie dostępne nagrania BBC Learning English („6 Minute English") osadzone przez ten sam odtwarzacz YouTube co moduł słuchania w Linguo — każde pytanie sprawdzone względem faktycznie pobranej transkrypcji nagrania (tą samą biblioteką co lib/listening/fetch-transcript.ts), a nie zgadywane. Wypowiedź pisemna: lekcja z pełnym rozkładem punktowym CKE (12 pkt podstawowa / 13 pkt rozszerzona, źródło: oficjalny Informator o egzaminie maturalnym), przydatnymi zwrotami i jednym w pełni omówionym przykładem na maksimum punktów per poziom, plus bank zadań (e-mail/wpis na blogu na podstawie — w tym prawdziwe tematy z Informatora CKE; rozprawka za i przeciw na rozszerzonym — w tym prawdziwe tematy z matur 2023-2025) z własną, oryginalną wzorcową odpowiedzią odsłanianą po wysłaniu własnej pracy. Ocena wypowiedzi pisemnej jest analityczna wg 4 kryteriów CKE (Groq, z twardo wymuszaną w kodzie zasadą „gilotyny" długości tekstu — poniżej progu słów pozostałe kryteria są zerowane niezależnie od oceny AI), nie jednym zbiorczym wynikiem. Panel administratora (/matura/admin/import, widoczny na dashboardzie tylko dla role = 'admin') pozwala wgrać dowolny arkusz maturalny z poprzednich lat jako PDF (opcjonalnie razem z osobnym plikiem klucza odpowiedzi, co poprawia trafność odpowiedzi w zadaniach zamkniętych) — AI wyodrębnia z niego zadania środków językowych, czytania i pisania (zawsze source: 'curated' + needsReview: true, świadomie ostrożniejsze niż automatyczny pipeline Matmy, bo nie da się algorytmicznie zweryfikować, że wgrany PDF to naprawdę niezmieniony arkusz CKE — patrz lib/matura/import-pdf.ts). „Rozumienie ze słuchu" jest z tego importu świadomie wykluczone: arkusz to sam tekst, bez nagrania, a CKE nawet nie drukuje transkrypcji zadań na słuchanie. Schemat bazy (supabase/migrations/0013_matura.sql, 0014_matura_writing.sql, 0020_matura_language.sql, 0021_matura_theory.sql) jest już przygotowany na resztę docelowego zakresu: symulacje egzaminu, plan nauki do dnia matury, przydzielanie ćwiczeń uczniom — czekają na UI w kolejnych sesjach.

Uwaga historyczna. Przez pewien czas w repo istniała druga, równoległa implementacja teorii i słownictwa dla matury (matura_grammar_topics, matura_vocabulary_words, trasy /matura/nauka/gramatyka i /matura/nauka/slownictwo), zbudowana w innej sesji. Została wycofana migracją 0022, bo nie miała wymiaru języka — jej tabele nie mają kolumny language, a kolumna z hasłem nazywa się word_en. Skutek był taki, że uczeń, który wybrał hiszpański, i tak dostawał angielską teorię i angielskie słówka. Obecna wersja rozdziela treść językiem od pierwszego dnia.

Algorytmy (/algorytmy) — interaktywna nauka struktur danych i algorytmów. Dwanaście działów ułożonych w łańcuch zależności, nie w taksonomię: złożoność jako pierwsza, bo w jej języku opisuje się każdy kolejny dział; rekurencja przed drzewami, bo przechodzenie drzewa JEST rekurencją; sortowanie przed kopcami, bo kopiec odpowiada na pytanie „skoro sortowanie daje n log n, czy da się wyciągnąć minimum taniej?". Uzasadnienie kolejności siedzi w lib/algorytmy/topics.ts.

Lekcje nie są ścianą tekstu o algorytmach — pokazują je w działaniu. Bloki interaktywne (lib/algorytmy/lesson-blocks.ts) uruchamiają prawdziwy algorytm na zapisanych danych i zapisują każdą klatkę: sortowanie bąbelkowe, przez wstawianie, przez wybór, przez scalanie i szybkie z podświetlonymi porównaniami i zamianami; BFS i DFS na grafie SVG; wyszukiwanie binarne z odrzucanymi połówkami; stos i kolejka odtwarzające tę samą listę operacji obok siebie; wykres rzędów wzrostu. To celowe: animacja pisana ręcznie może po cichu rozminąć się z algorytmem, który rzekomo pokazuje, a tutaj ciąg klatek JEST śladem wykonania, więc obrazek nie może skłamać. Reszta bloków to definicje, tabele złożoności, kod, porównania i quizy sprawdzające zrozumienie w trakcie czytania (bez punktów — od oceniania są zadania).

Zadania działają tak samo jak w Maturze i Geografii: dział listuje typy zadań (złożoność, wynik kodu, krok algorytmu, dobór struktury, pojęcia, analiza błędu) z licznikiem wykonań i skutecznością, a wejście w typ wydaje zadanie, którego jeszcze nie rozwiązywałeś — lib/algorytmy/exercise-stock.ts dogenerowuje kolejne, gdy zapas się kończy. Wszystkie zadania są jednokrotnego wyboru, świadomie: odpowiedź otwartą o algorytmie oceniałby model, a jego werdyktu nikt nie umie sprawdzić. Teoria pisana jest jako JSON w supabase/seed/algorytmy/ lessons/*.json i walidowana przez node scripts/algorytmy-build-lessons.mjs, który odmawia wygenerowania SQL-a m.in. dla nieposortowanej tablicy w bloku wyszukiwania binarnego (algorytm pokazałby wtedy poprawne kroki prowadzące do złej odpowiedzi) i dla krawędzi wskazującej nieistniejący wierzchołek.

Gitara (/gitara) — nauka gry na gitarze od zera: akordy, nuty i rytm, system CAGED, techniki gry, biblioteka akordów i piosenek, metronom i stroik. Pięć działów w kolejności zależności, nie w taksonomię — postawa i strojenie jako pierwszy dział, bo nic innego nie da się ćwiczyć na rozstrojonej gitarze; pierwsze akordy przed nutami i rytmem, bo to one utrzymują motywację początkującego; CAGED dopiero po obu, bo jest dosłownie tymi samymi pięcioma kształtami akordów przesuwanymi po gryfie poznanym w dziale o nutach. Uzasadnienie kolejności w lib/gitara/topics.ts.

Bloki interaktywne (lib/gitara/lesson-blocks.ts) liczą prawdziwą teorię muzyki (lib/gitara/theory.ts), nie rysują statycznych obrazków: diagram akordu i przebieg progresji odtwarzane prawdziwym syntezatorem strun (Karplus-Strong przez Web Audio API, bez próbek audio), pięć kształtów CAGED wyprowadzonych transpozycją prawdziwych otwartych akordów C-A-G-E-D (z jednym efektem ubocznym wartym uwagi: kształty G i E dla tego samego akordu wychodzą na tym samym progu struny basowej, bo dzielą tę samą strunę root — dlatego G jest w praktyce rzadziej grywany, co wynika z matematyki transpozycji, nie jest arbitralną notatką), klikalny gryf („znajdź wszystkie C") i wartości rytmiczne wystukiwane w rzeczywistym tempie. Poprawność muzyczna całej biblioteki (nuty każdego akordu, dźwięk każdego pola gryfu, root każdego kształtu CAGED) jest zweryfikowana programowo przy tworzeniu danych startowych, nie tylko oceniona „na oko".

Aplikacja świadomie nie ma banku zadań w stylu Algorytmów czy Matury: każde pytanie, jakie da się zadać o gryfie czy akordzie („jaka to nuta", „jaki to akord"), da się wygenerować i ocenić deterministycznie z lib/gitara/theory.ts — nie ma tu żadnej ukrytej odpowiedzi wartej chronienia po stronie serwera, więc ćwiczenia (np. blok fretboard-explorer) generują się i oceniają w przeglądarce, a gtr_drill_attempts zapisuje wyłącznie wynik. Biblioteka akordów (/gitara/akordy) i piosenek (/gitara/piosenki) to osobne, przeglądalne zasoby poza lekcjami; import śpiewnika z PDF-a (app/api/gitara/import-songbook/route.ts) działa jak w Scholi — AI dzieli plik na piosenki w formacie ChordPro, człowiek poprawia przed zapisem, dopiero wtedy trafiają do bazy. Startowa biblioteka piosenek to wyłącznie utwory tradycyjne/ludowe bez ustalonego autorstwa („Wlazł kotek na płotek", „Sto lat", „Cicha noc", „Płonie ognisko") — świadomie, bo spec wymaga zgody na rozpowszechnianie tabulatur, a tej zgody nie da się zweryfikować automatycznie dla dowolnej współczesnej piosenki. /gitara/cwicz to metronom (harmonogram z wyprzedzeniem, ta sama technika co w prawdziwych aplikacjach audio, żeby tempo nie driftowało pod jitterem JS-owej pętli zdarzeń) i stroik chromatyczny z detekcją wysokości dźwięku przez mikrofon (autokorelacja, Web Audio API) — z jawną obsługą braku dostępu do mikrofonu, zgodnie ze specem („alternatywna ścieżka bez analizy dźwięku"). Schemat: supabase/migrations/0025_gitara.sql, treść startowa: supabase/seed/gitara/*.sql.

Godziny (/godziny) — dziennik czasu nauki: ile minut i czego się dziś uczyłeś. Wpis to data + długość sesji + temat z własnej listy (+ opcjonalna notatka), a ekran główny odpowiada na jedno pytanie — „ile dziś zrobiłem i co ostatnio robiłem": kafelki dziś/tydzień/ miesiąc, seria dni z rzędu i stream ostatnich wpisów pogrupowany po dniach, z edycją i kasowaniem w miejscu. /godziny/historia daje ten sam materiał w przekroju: przełącznik dni/tygodnie/miesiące, filtr po temacie (oba trzymane w URL-u, więc dają się zapisać w zakładkach), wykres słupkowy sumy czasu w kolejnych okresach oraz rozbicie „na co poszedł czas". Listą tematów zarządza się na /godziny/tematy — startowy zestaw (przedmioty szkolne, rozwój własny oraz aplikacje edukacyjne z samego Phoenixa, czytane z lib/phoenix/apps.ts) wchodzi na jedno kliknięcie i jest w całości edytowalny.

Dwie decyzje, które warto znać przed grzebaniem w tym module. Po pierwsze: wiele wpisów tego samego dnia jest dozwolone, także dla tego samego tematu — spec zostawiała ten wybór otwarty, a nauka realnie rozbija się na sesje (rano 30 min, wieczorem 45 min) i notatka opisuje sesję, nie dzień; sumowanie jest sprawą widoku, nie schematu. Po drugie: temat z zapisanymi godzinami da się tylko zarchiwizować, nie skasować — historia nigdy nie zostaje z dziurą po nazwie. Klucz obcy study_sessions.topic_id ma mimo to on delete cascade, a nie restrict, wyłącznie po to, żeby kasowanie profilu nie wywracało się na kolejności kaskad; regułę egzekwuje deleteTopic() w lib/godziny/topic-actions.ts (uzasadnienie w komentarzu w 0020_godziny.sql). Walidacji „data nie z przyszłości" nie da się zapisać jako CHECK (current_date jest STABLE, a Postgres wymaga tam funkcji IMMUTABLE), więc pilnuje jej lib/godziny/actions.ts — w strefie Europe/Warsaw, żeby wpis zrobiony o 23:30 nie wyglądał na jutrzejszy. Schemat: supabase/migrations/0020_godziny.sql — numer 0020, a nie kolejny wolny w repo, bo wersje 0018 i 0019 są już zajęte na bazie deweloperskiej przez migracje wdrożone równolegle z innych sesji/worktree (geografia_lessons, modlitwa_brewiarz), których pliki nie trafiły jeszcze na main. Runner z scripts/db.mjs rozpoznaje migracje po numerze wersji, nie po pełnej nazwie pliku, więc plik z zajętym numerem nie zgłosiłby konfliktu — zostałby po cichu uznany za „już wgrany" i nigdy by się nie wykonał. Dlatego przed dodaniem migracji zawsze npm run db status.

⚠️ Migracja 0015 w numeracji jest zajęta przez inną, niepowiązaną funkcję („geografia") wdrożoną równolegle na tej samej bazie deweloperskiej z innej sesji/worktree — dlatego migracja teorii Matury nosi numer 0016, nie 0015. Przed dodaniem kolejnej migracji sprawdź npm run db status, żeby uniknąć podobnej kolizji numeracji.

Schola (/schola) jest inna niż powyższe — to NIE jest mini-aplikacja Phoenixa (nie ma wpisu w lib/phoenix/apps.ts, nie pojawia się na /aplikacje ani na launcherze /). To w pełni osobny realm dla scholi kościelnej: własna rejestracja/logowanie (/schola/logowanie, /schola/rejestracja), własna powłoka bez dolnej nawigacji Phoenixa — użytkownicy Scholi nigdy nie widzą reszty Phoenixa. Mimo to działa w tym samym wdrożeniu Next.js i tym samym projekcie Supabase (dla prostoty hostingu), z osobną tabelą członkostwa schola_members (niezależną od profiles) i politykami RLS opartymi o is_schola_member() zamiast własności wiersza — każdy zalogowany członek scholi może edytować każdą pieśń i każdy plan. Funkcje: śpiewnik (tytuł, tekst z akordami w formacie ChordPro, tagi liturgiczne, linki do nagrań/nut), planowanie Mszy (uporządkowana lista pieśni z notatkami typu „2x refren, 1x zwrotka"), import całego śpiewnika z PDF-a (AI dzieli plik na pojedyncze pieśni) oraz import pojedynczej pieśni ze zdjęcia nut/tekstu z akordami — oba z obowiązkowym ekranem korekty przed zapisem, ten sam schemat co w Paragonach. Zob. supabase/migrations/0009_schola.sql i lib/schola/* po szczegóły; osoba z istniejącym kontem Phoenixa, która chce dołączyć do Scholi, loguje się tym samym e-mailem na /schola/logowanie (patrz komentarz „Sharp edges” w planie implementacji, jeśli szukasz uzasadnienia tej decyzji).

Spis treści

Stack technologiczny

  • Next.js 16 (App Router, Turbopack) + TypeScript
  • Tailwind CSS v4 — projekt mobile-first, dolna nawigacja jak w aplikacji mobilnej
  • Supabase — Postgres, autentykacja e-mail/hasło, Row Level Security
  • Groq API (Llama 3.3) — generowanie i ocenianie treści, wyłącznie po stronie serwera, darmowy tier
  • youtube-transcript — pobieranie transkrypcji filmów YouTube do modułu słuchania

Next.js 16 zmienił konwencję middleware.ts na proxy.ts (patrz proxy.ts w katalogu głównym) — jeśli coś aktualizujesz w oparciu o starsze przykłady z internetu, uwzględnij tę zmianę.

Funkcje

  1. Wybór języka — aplikacja uczy angielskiego, hiszpańskiego lub rosyjskiego (dla osób mówiących po polsku). Język wybierasz przy zakładaniu konta i możesz go zmienić w profilu — wszystkie treści (słówka, gramatyka, teksty, piosenki) przełączają się na wybrany język.
  2. Autentykacja i profil — rejestracja/logowanie e-mail+hasło, wybór języka i poziomu (A1-B2) zaraz po rejestracji, zmiana w profilu, tryb jasny/ciemny.
  3. Ścieżka nauki — mapa etapów per poziom (kategoria słówek + powiązany temat gramatyczny na etap); kolejny etap odblokowuje się po opanowaniu 80% słówek z bieżącej kategorii. Admin widzi na jakim etapie jest każdy uczeń i może jednym kliknięciem zadać temu uczniowi pracę domową z zaległej kategorii.
  4. Słówka — fiszki z animacją obrotu i prostym algorytmem powtórek + trener znaczeń; oba tryby wspierają ćwiczenie pojedynczej kategorii (np. z poziomu ścieżki nauki).
  5. Łączenie tłumaczeń — gra: łączysz słowo w języku obcym z jego polskim tłumaczeniem (rysowana linia). Można z niej zadać pracę domową.
  6. Gramatyka — tematy per poziom z wyjaśnieniami po polsku, ćwiczenia (luki, wybór, przekształcenia zdań oceniane przez AI).
  7. Czytanie — AI generuje krótkie artykuły w wybranym języku, dopasowane do poziomu i tematu, zadaje pytania (ABCD + otwarte), ocenia odpowiedzi otwarte.
  8. Pisanie — krótkie formy (bez esejów) z losowym, konkretnym poleceniem od AI, ocena poprawności/słownictwa, poprawiona wersja tekstu, mini-dialog pogłębiający.
  9. Piosenki — wklejasz tekst piosenki, tłumaczysz linijka po linijce (AI akceptuje sensowne warianty); tryb „Słówka" pozwala dotknąć dowolnego słowa, by zobaczyć jego znaczenie w kontekście.
  10. Słuchanie — wklejasz link do YouTube, aplikacja pobiera transkrypcję i tworzy ćwiczenie z lukami; kliknięcie luki przewija film do właściwego momentu.
  11. Prace domowe — admin tworzy zadania (9 typów) dla całego poziomu lub konkretnego ucznia, może edytować ich treść, a każde zadanie ma jasny opis wymagań; postęp liczy się automatycznie.
  12. Kalendarz i streaki — kalendarz miesięczny z oznaczonymi dniami aktywności, aktualny streak i rekord, zbiorcze statystyki.

Uruchomienie lokalne

Wymagania: Node.js 20.9+ (zalecane 22+), konto Supabase, klucz API Groq (do funkcji AI, darmowy).

npm install
cp .env.example .env.local   # uzupełnij wartości — patrz niżej
npm run dev

Aplikacja wystartuje na http://localhost:3000.

Konfiguracja Supabase

  1. Utwórz nowy projekt na supabase.com.

  2. W SQL Editor uruchom po kolei zawartość plików z katalogu supabase/ (albo z terminala — patrz Wgrywanie migracji z terminala):

    Migracje (schemat):

    1. supabase/migrations/0001_init.sql — schemat bazy (tabele, enumy, RLS, funkcje).
    2. supabase/migrations/0002_learning_path.sql — tabela ścieżki nauki (etapy per poziom).
    3. supabase/migrations/0003_multilang_homework_matching.sql — wielojęzyczność (kolumna language + profiles.target_language), prace domowe per-uczeń, gra „łączenie tłumaczeń", polityki RLS admin-read (dzięki nim admin widzi postęp uczniów).
    4. supabase/migrations/0004_writing_tasks_insert_own.sql — polityka RLS pozwalająca uczniom generować zadania pisemne.
    5. supabase/migrations/0005_phoenix_installed_apps.sql — kolumna installed_apps (aplikacje widoczne na launcherze Phoenixa).
    6. supabase/migrations/0006_prompt_forge.sql — tabela prompt_sessions (Kuźnia: sesje kreatora promptów).
    7. supabase/migrations/0007_matma.sql — schemat Matmy (matura rozszerzona z matematyki): działy, lekcje, bank zadań, próby, egzaminy próbne, postęp per dział, ścieżka nauki, migawki postępu, plan nauki, przypisane ćwiczenia; tworzy też prywatny bucket Storage math-attempts na zdjęcia brudnopisu.
    8. supabase/migrations/0008_paragony_budzet_etf.sql — schemat Paragonów: konta, kategorie budżetowe, paragony + pozycje, transakcje (uznanie/obciążenie/transfer), rachunki cykliczne, cele oszczędnościowe, budżet miesięczny, portfel ETF (holdingi, transakcje kupna/sprzedaży, dywidendy) oraz globalny cache cen etf_price_history (bez RLS per-user — patrz komentarz w migracji); tworzy też prywatny bucket Storage paragony-receipts na zdjęcia paragonów.
    9. supabase/migrations/0009_schola.sql — schemat Scholi (osobny realm, patrz wyżej): schola_members (osobne członkostwo, niezależne od profiles), schola_songs (śpiewnik), schola_mass_plans + schola_mass_plan_items (planowanie Mszy); RLS oparta o funkcję is_schola_member(), nie o własność wiersza — brak bucketu Storage (import PDF/zdjęcia jest przetwarzany tymczasowo, nic nie jest trwale zapisywane).
    10. supabase/migrations/0013_matura.sql — schemat Matury Angielski: cztery części egzaminu per poziom (matura_sections), lekcje, bank zadań, próby, symulacje egzaminu, postęp per część, migawki postępu, plan nauki, przydzielone ćwiczenia i wybrany poziom matury (matura_settings) — pełny docelowy zakres (patrz opis aplikacji wyżej).
    11. supabase/migrations/0014_matura_writing.sql — schemat „Wypowiedzi pisemnej": matura_writing_tasks (bank zadań z wzorcową odpowiedzią) i matura_writing_submissions (oceniane analitycznie przez AI wg 4 kryteriów CKE, patrz opis aplikacji wyżej) — osobne tabele od matura_tasks/matura_task_attempts z 0013, bo ocena jest holistyczna, nie dopasowaniem pojedynczych odpowiedzi.
    12. supabase/migrations/0020_matura_language.sql — wymiar języka w Maturze: kolumna language w matura_sections i w tabelach per-użytkownik, które trzymają poziom bez section_id. Wszystko, co wisi na section_id, język DZIEDZICZY, zamiast trzymać kopię, która mogłaby się rozjechać. Domyślne 'en' sprawia, że istniejąca treść i postęp uczniów przechodzą migrację bez backfillu.
    13. supabase/migrations/0021_matura_theory.sql — biblioteka teorii i bank słownictwa: matura_lessons dostaje slug (własny adres lekcji), summary, kind (gramatyka/słownictwo/strategia) i szacowany czas; dochodzi matura_lesson_progress (znacznik „przerobione") oraz matura_vocab_topics / _entries / _progress (bloki tematyczne, hasła, powtórki na pudełkach Leitnera). Osobne tabele od vocabulary_words z 0001 — tamte są kluczowane poziomem CEFR, nie maturalnym, nie mają miejsca na tłumaczenie przykładu ani notatkę, a czyta je nieprzefiltrowany trener fiszek Linguo (wgranie tam haseł maturalnych zmieniłoby po cichu, czego uczy inna aplikacja). Uwaga: matura_lessons.slug jest NOT NULL, więc seedy lekcji trzeba uruchomić po tej migracji.
    14. supabase/migrations/0023_matura_task_types.sql — typ zadania CKE na każdym wierszu matura_tasks (kolumna task_type), czyli oś, wokół której ćwiczy się zamiast ponumerowanej listy. Klasyfikacja siedzi w funkcji matura_infer_task_type (polecenie + kształt itemów) i w triggerze BEFORE INSERT/UPDATE, a nie w jednorazowym UPDATE — seedy kasują i wstawiają swoje wiersze przy każdym uruchomieniu, więc jednorazowy backfill zgubiłby klasyfikację przy najbliższym npm run db seed. Reguły sprawdzono na komplecie supabase/seed/matura/ i matura-es/: każde zaseedowane zadanie trafia we właściwy typ. Wypowiedź pisemna nie dostaje kolumny — jej typem jest form_type, ta migracja tylko poszerza dopuszczalne wartości o artykul i list_formalny. Numer 0023 sprawdź przez npm run db status przed wgraniem — patrz ostrzeżenie o kolizjach numeracji wyżej.
    15. supabase/migrations/0024_algorytmy.sql — schemat aplikacji Algorytmy: algo_topics, algo_lessons + algo_lesson_progress, algo_exercises (bank jednokrotnego wyboru z task_type NOT NULL od początku — w przeciwieństwie do Matury, gdzie kolumnę trzeba było dołożyć do istniejącego banku) oraz algo_exercise_attempts. Polityka algo_exercises_insert_own dopuszcza wiersz, którego created_by to wołający — dzięki temu kolejka ćwiczeń dogenerowuje zadania bez klucza service-role, dokładnie tak jak geo_exercises. Ten sam warunek: npm run db status przed wgraniem.

    Seed — konto admina: 8. supabase/seed/00_admin.sql — konto administratora (patrz niżej).

    Seed — angielski (język domyślny): 9. 01_vocabulary_a1.sql01_vocabulary_b2.sql — słownictwo EN (~1000 słówek). 10. 02_grammar_a1.sql02_grammar_b2.sql — gramatyka EN (5 tematów × ~30 ćwiczeń/poziom). 11. 03_learning_path.sql — ścieżka nauki EN.

    Seed — hiszpański (opcjonalnie, jeśli chcesz język ES): 12. es_01_vocabulary_a1.sqles_01_vocabulary_b2.sql, es_02_grammar_a1.sqles_02_grammar_b2.sql, a na końcu es_03_learning_path.sql.

    Seed — rosyjski (opcjonalnie, jeśli chcesz język RU): 13. ru_01_vocabulary_a1.sqlru_02_grammar_b2.sql, a na końcu ru_03_learning_path.sql.

    Seed — Matma: 14. supabase/seed/matma/01_topics.sql — 11 działów matury rozszerzonej z matematyki

    • rekomendowana kolejność (ścieżka nauki).
    1. supabase/seed/matma/02_lessons_<dzial>.sql i 03_problems_<dzial>.sql (po jednej parze plików na dział, 11 par) — interaktywne lekcje i bank zadań (źródło topic). Uruchom 01_topics.sql przed nimi (odwołują się do działów po slug).
    2. Prawdziwe zadania maturalne CKE (source: 'past_exam') nie są w plikach seed — importuje je administrator jednorazowym skryptem z panelu /matma/admin/import (patrz lib/matma/import-past-exams.ts), nie jest to część standardowego seedowania.

    Seed — Matura (angielski): 17. supabase/seed/matura/01_sections.sql — 4 części egzaminu × 2 poziomy (matura_sections), z wagami punktowymi (przybliżenie, patrz opis aplikacji wyżej). 18. supabase/seed/matura/02_lessons_srodki_jezykowe.sql (poziom podstawowy, 10 lekcji) i 17_lessons_srodki_rozszerzona.sql (rozszerzony, 10 lekcji) — teoria działu „Znajomość środków językowych". Podział na dwa pliki jest po poziomie, bo razem przekraczają dwa tysiące linii. Treść jsonb w formacie GrammarBlock — ten sam renderer co lekcje gramatyki w Linguo, poszerzony w 0017 o bloki ćwiczeniowe. Uruchom 01_sections.sql wcześniej. 19. supabase/seed/matura/03_tasks_srodki_jezykowe.sql — kuratorowany bank zadań (source: 'curated'), po 3 zadania na poziom. Uruchom 01_sections.sql wcześniej. 20. supabase/seed/matura/04_lessons_pisanie.sql — 8 lekcji (4 na poziom) dla działu „Wypowiedź pisemna", ułożonych wokół kryteriów oceniania, a nie wokół „jak dobrze pisać": kryteria się publikuje, więc da się nauczyć dokładnie tego, co liczy egzaminator. Punktacja musi zostać zgodna z lib/matura/writing-grading.ts, który tymi samymi kryteriami karmi oceniające AI. Uruchom 01_sections.sql wcześniej. 21. supabase/seed/matura/05_writing_tasks_podstawowa.sql i 06_writing_tasks_rozszerzona.sql — bank zadań pisemnych (matura_writing_tasks), 4 na poziom, część z prawdziwych tematów CKE (source: 'past_exam') — patrz komentarz w każdym pliku po dokładne źródło — reszta oryginalne (source: 'curated'). Każde zadanie ma własną, oryginalną wzorcową odpowiedź. Uruchom 01_sections.sql wcześniej. 22. supabase/seed/matura/07_lessons_czytanie.sql i 08_tasks_czytanie.sql — 5 lekcji

    • kuratorowany bank zadań (source: 'curated') dla „Rozumienia tekstów pisanych", po 3 zadania na poziom — oryginalne teksty w typach zadań prawdziwych arkuszy CKE (dopasowanie nagłówków, prawda/fałsz, tekst z lukami zdaniowymi, dopasowanie pytań do fragmentów). Lekcje są w większości kind='strategia', bo w tym dziale punkty traci się na metodzie, nie na języku. Uruchom 01_sections.sql wcześniej.
    1. supabase/seed/matura/09_lessons_sluchanie.sql i 10_tasks_sluchanie.sql — 5 lekcji + kuratorowany bank zadań dla „Rozumienia ze słuchu", po 2 zadania na poziom, każde osadzające prawdziwe nagranie BBC Learning English („6 Minute English", content.youtubeVideoId) — pytania zweryfikowane względem faktycznie pobranej transkrypcji nagrania, nie zgadywane. Uruchom 01_sections.sql wcześniej.
    2. supabase/seed/matura/11_vocab_topics.sql — 15 bloków tematycznych zakresu z podstawy programowej. Uruchom przed plikami 1216, które szukają bloku po slug. Piętnasty blok (realioznawstwo) NIE jest blokiem z podstawy i jest tak opisany — pokrywa osobny wymóg CKE dotyczący wiedzy o krajach obszaru językowego.
    3. supabase/seed/matura/12_vocab_*.sql16_vocab_*.sql — 425 haseł angielskich, po trzy bloki na plik. Kolumna note niesie to, czego para hasło–tłumaczenie nie unosi, a co realnie decyduje o punktach: niepoliczalność (homework, luggage, research), kolokacje (take vs pass an exam, do vs make research), przyimki ukryte przez polskie tłumaczenie (good AT, rely ON) i fałszywi przyjaciele (sympathetic, novel, prejudice, pension).

    Seed — Matura (hiszpański): komplet niezależny od angielskiego, w katalogu supabase/seed/matura-es/. Wymaga wcześniej migracji 0020_matura_language.sql. 26. matura-es/01_sections.sql — te same 4 części × 2 poziomy, tym razem z language = 'es'. Uruchom przed pozostałymi plikami z tego katalogu. 27. matura-es/02_lessons_srodki_jezykowe.sql (podstawowa, 10 lekcji), 17_lessons_srodki_rozszerzona.sql (rozszerzona, 9 lekcji) i 03_tasks_srodki_jezykowe.sql (bank zadań: 3 na podstawie, 4 na rozszerzeniu). Kolejność lekcji jest podyktowana tym, ile dana rzecz kosztuje punktów, a nie układem podręcznika: najpierw ser/estar i por/para (są w prawie każdym arkuszu, a polski nie pomaga przy żadnym), potem rodzajniki (polski nie ma ich wcale), dopiero potem czasy przeszłe. Rozszerzenie: subjuntivo, okresy warunkowe, mowa zależna, perífrasis, strona bierna i SE, parafrazy. 28. matura-es/04_lessons_pisanie.sql (8 lekcji), 05_writing_tasks_podstawowa.sql, 06_writing_tasks_rozszerzona.sql — teoria + po 3 zadania na poziom, każde z własną oryginalną wzorcową odpowiedzią. Wszystkie oznaczone source: 'curated' (nie past_exam) — są pisane w formacie CKE, ale nie są przepisanymi arkuszami, więc etykieta „prawdziwe zadanie CKE" byłaby nieuczciwa. 29. matura-es/07_lessons_czytanie.sql i 08_tasks_czytanie.sql — 5 lekcji + po 2 zadania na poziom, oryginalne teksty w formatach CKE (wybór wielokrotny, dobieranie nagłówków, intencja autora, uzupełnianie luk zdaniami). 30. matura-es/09_lessons_sluchanie.sqltylko lekcje (5), bez zadań. Zadanie ze słuchu wymaga content.youtubeVideoId wskazującego na realne, wciąż dostępne nagranie; wymyślony identyfikator dałby uczniowi martwy odtwarzacz, co jest gorsze niż uczciwy stan „brak zadań". Skoro teoria niesie tu cały dział sama, jest odpowiednio obszerniejsza — z osobną lekcją o hiszpańszczyźnie mówionej (vale, o sea, połykane końcówki -ado) i o różnicach Hiszpania/Ameryka. Zadania hiszpańskie dodaj tak samo jak angielskie: wybierz nagranie, zweryfikuj identyfikator, dopiero potem napisz pytania. 31. matura-es/11_vocab_topics.sql — te same 15 bloków tematycznych co po angielsku, z tymi samymi slug, żeby uczeń przełączający język trafiał na ten sam blok, a nie na inny. Uruchom przed plikami 1216. 32. matura-es/12_vocab_*.sql16_vocab_*.sql — 513 haseł hiszpańskich. W kolumnie note to, na czym Polacy realnie tracą punkty: el pelo w liczbie pojedynczej mimo polskiej mnogiej, las gafas zawsze w mnogiej, caer bien ze składnią jak gustar, el mapa i el problema rodzaju męskiego mimo końcówki -a, oraz fałszywi przyjaciele w rodzaju embarazada.

    Każdy plik seeda usuwa najpierw swoje dane (delete ... where language = ... and level = ...), więc można je bezpiecznie uruchomić ponownie — pliki jednego języka nie ruszają danych pozostałych języków. *_03_learning_path.sql wymaga wcześniej uruchomionych plików ze słownictwem i gramatyką danego języka (odwołuje się do ich kategorii i tematów).

    ⚠️ Ponowne uruchomienie seeda słownictwa danego języka wstawia słówka z nowymi ID, więc kasuje postęp opanowania słówek (vocabulary_progress) tego języka — to skutek kaskady kluczy obcych, nie błąd. Uruchamiaj ponownie tylko wtedy, gdy naprawdę chcesz odświeżyć pulę słówek.

    ⚠️ Seedy gramatyki (*02_grammar_*.sql) czyszczą też etapy ścieżki nauki swojego języka (etapy wskazują na tematy gramatyczne kluczem obcym). Po ich ponownym uruchomieniu zawsze uruchom na końcu *_03_learning_path.sql tego języka, żeby odtworzyć ścieżkę.

  3. W Authentication → Providers upewnij się, że logowanie e-mail/hasło jest włączone. Do szybkich testów lokalnych możesz wyłączyć "Confirm email" w Authentication → Sign In / Providers, żeby rejestracja od razu dawała aktywną sesję (w przeciwnym razie użytkownik musi potwierdzić adres e-mail przed pierwszym logowaniem).

  4. Skopiuj Project URL, anon public key i service_role key z Project Settings → API do .env.local.

Wgrywanie migracji z terminala

Zamiast klikać w SQL Editor można puścić migracje skryptem scripts/db.mjs. Wymaga jednej dodatkowej zmiennej w .env.local — connection stringu z Project Settings → Database → Connection string → Session pooler (port 5432; „Direct connection" jest IPv6-only i zwykle nie łączy się z domowego łącza), z [YOUR-PASSWORD] podmienionym na hasło do bazy:

SUPABASE_DB_URL=postgresql://postgres.<ref>:<haslo>@aws-0-<region>.pooler.supabase.com:5432/postgres
npm run db status              # co jest wgrane, co czeka
npm run db baseline            # jednorazowo: oznacz już wklejone migracje jako wgrane
npm run db up                  # wgraj oczekujące migracje (każda w transakcji)
npm run db up -- --dry-run     # tylko pokaż, co poszłoby na bazę
npm run db sql supabase/seed/00_admin.sql
npm run db query "select count(*) from profiles"

Skrypt trzyma rejestr wgranych migracji w tabeli public._migrations (wersja, nazwa, suma kontrolna pliku, data) — z włączonym RLS i odebranymi uprawnieniami dla anon/authenticated, więc nie wychodzi przez PostgREST. status oznacza migrację jako zmieniony, jeśli plik różni się od tego, co faktycznie poszło na bazę.

Na istniejącej bazie, gdzie migracje 00010009 wklejano ręcznie, uruchom najpierw npm run db baseline — zapisze je w rejestrze bez wykonywania SQL. Bez tego up spróbowałoby wgrać je od nowa. Na czystej bazie pomiń baseline i od razu zrób up.

Plik migracji, który nie może działać w transakcji (np. CREATE INDEX CONCURRENTLY), oznacz komentarzem -- no-transaction w pierwszych liniach — skrypt puści go wtedy bez własnego BEGIN/COMMIT.

SUPABASE_DB_URL zawiera hasło do bazy i omija RLS. Trzyma się je wyłącznie w .env.local (jest w .gitignore) — nie dodawaj go do zmiennych środowiskowych na Vercelu, aplikacja go nie używa.

Cała logika Row Level Security (kto co widzi/edytuje) jest już zdefiniowana w migracji: własne postępy widzi tylko właściciel, treści współdzielone (słówka, gramatyka, prace domowe) są czytelne dla każdego zalogowanego użytkownika, a zapis do nich wymaga roli admin.

Zmienne środowiskowe

Patrz .env.example. Wymagane:

Zmienna Opis
NEXT_PUBLIC_SUPABASE_URL URL projektu Supabase
NEXT_PUBLIC_SUPABASE_ANON_KEY publiczny klucz anon Supabase
SUPABASE_SERVICE_ROLE_KEY klucz service_role — tylko po stronie serwera, używany m.in. do logowania po nazwie użytkownika
GROQ_API_KEY klucz API Groq — funkcje AI (czytanie, pisanie, piosenki, gramatyka-przekształcenia) nie zadziałają bez niego, darmowy tier na console.groq.com
NEXT_PUBLIC_SITE_URL publiczny URL wdrożenia (linki w e-mailach autoryzacyjnych)

Opcjonalnie: GROQ_MODEL (domyślnie llama-3.3-70b-versatile), FMP_API_KEY — klucz Financial Modeling Prep (darmowy tier: 250 zapytań/dzień) używany przez Paragony do cen ETF-ów zagranicznych; bez niego działają nadal ETF-y notowane na GPW (Stooq, bez klucza) — patrz lib/paragony/etf-prices.ts.

Konto administratora

Seed (supabase/seed/00_admin.sql) tworzy konto administratora bezpośrednio w schemacie auth Supabase:

  • login: admin
  • hasło: admin213

Logowanie w aplikacji akceptuje login lub e-mail — dla konta admina wystarczy wpisać admin.

⚠️ To hasło jest publiczne (jest w tym repozytorium). Przed jakimkolwiek wdrożeniem produkcyjnym/publicznym zmień je w Supabase Dashboard → Authentication → Users → admin → Reset password, albo usuń to konto i utwórz własne z rolą admin w tabeli profiles.

Testy end-to-end

Playwright — bez mocka backendu, testy klikają po prawdziwej aplikacji gadającej z prawdziwym Supabase (tak jak npm run dev), łącznie z prawdziwym ocenianiem AI. Na razie pokrywają moduł Matura z języka:

npm run test:e2e       # wymaga wgranego seeda Matury i .env.local, patrz e2e/README.md
npm run test:e2e:ui    # tryb interaktywny

Szczegóły (co jest pokryte, jak działają jednorazowe konta testowe) w e2e/README.md.

Struktura projektu

app/
  (main)/            # ekrany za logowaniem — wspólny layout z dolną nawigacją
    page.tsx          # PHOENIX: launcher (kafelki zainstalowanych aplikacji)
    aplikacje/         # PHOENIX: menedżer aplikacji (dodaj/usuń z ekranu głównego)
    profil/            # PHOENIX: profil, poziom, język, motyw, wylogowanie
    jezyki/            # LINGUO — mini-aplikacja językowa
      page.tsx          # dashboard („Dziś"): streak, etap ścieżki, prace domowe
      nauka/             # hub + wszystkie moduły nauki (fiszki, gramatyka, ...)
      prace-domowe/      # widok prac domowych użytkownika
      kalendarz/         # kalendarz, streaki, statystyki
      admin/             # panel administratora (prace domowe, ścieżki uczniów)
    kuznia/            # KUŹNIA — kreator promptów
    godziny/           # GODZINY — licznik czasu nauki
      page.tsx          # „Dziś": sumy dzień/tydzień/miesiąc + stream wpisów
      historia/          # historia wg dni/tygodni/miesięcy + filtr po temacie
      tematy/            # lista tematów (zestaw startowy, archiwum)
    matma/             # MATMA — matura rozszerzona z matematyki
      page.tsx          # dashboard: szacowany wynik, mastery per dział, trend, plan
      nauka/             # hub działów, lekcje interaktywne, ćwiczenia
      diagnoza/          # test diagnostyczny startowy (opcjonalny, per dział)
      dowody/            # trener dowodów (przekrojowy, is_proof=true)
      egzamin/           # symulacja egzaminu (180 min / 50 pkt)
      plan/              # harmonogram nauki do daty matury
      kalendarz/         # kalendarz aktywności (reużywa components/calendar)
      admin/             # panel nauczyciela + import zadań maturalnych CKE
    matura/            # MATURA Z JĘZYKA — angielski albo hiszpański (CKE)
      page.tsx          # dashboard: wybór języka i poziomu / szacowany wynik
      nauka/             # hub 4 części egzaminu — wszystkie zbudowane
        [sectionSlug]/     # generyczna trasa dla 3 działów ocenianych dokładnym
                          # dopasowaniem: środki-jezykowe, czytanie, słuchanie
          teoria/[lessonSlug]/  # jedna lekcja teorii
          zadanie/[taskId]/     # jedno zadanie (osadza nagranie YouTube gdy
                                # content.youtubeVideoId jest ustawiony)
        pisanie/          # osobna trasa: teoria + bank zadań pisemnych + kompozycja
                          # oceniana przez AI (inny model danych — patrz opis wyżej)
          teoria/[lessonSlug]/  # trasa musi istnieć osobno: statyczny folder pisanie/
                                # przesłania segment [sectionSlug]; ciało jest wspólne
          zadanie/[taskId]/
      slownictwo/        # bank słownictwa — POZA nauka/, bo nie jest częścią arkusza
        dzial/[topicSlug]/       # jeden blok tematyczny: lista haseł z wyszukiwarką
          fiszki/                # trenażer jednego bloku
        powtorka/                # kolejka powtórek na dziś (Leitner, wszystkie bloki)
      ustawienia/        # zmiana języka i poziomu matury
      admin/import/      # panel admina: import arkusza PDF (+ opcjonalny klucz odpowiedzi)
  login/ register/ onboarding/   # ekrany publiczne / pierwsze logowanie
components/
  ui/                # podstawowe komponenty (Button, Card, Input, Badge, ...)
  layout/            # dolna nawigacja (per-aplikacja), nagłówek strony
  phoenix/           # komponenty powłoki (ikony aplikacji, menedżer)
  matma/             # komponenty Matmy: lesson/ (bloki lekcji), problem/ (rysik,
                     # ocena AI), exam/, diagnostic/, plan/, dashboard/, admin/
  matura/            # komponenty Matury: język i poziom, dashboard, lista części,
                     # próba zadania, trenażer słownictwa, lista haseł, stopka lekcji
                     # (treść lekcji renderuje components/grammar/lesson)
  algorytmy/         # bloki lekcji Algorytmów: statyczne (kod, tabela złożoności,
                     # porównanie) plus interaktywne wizualizatory sortowania, BFS/DFS,
                     # wyszukiwania binarnego, stosu/kolejki i rzędów wzrostu
  gitara/            # diagram akordu (SVG, współdzielony przez bibliotekę akordów, bloki
                     # lekcji i kształty CAGED), narzędzia metronomu/stroika, przepływ
                     # importu śpiewnika PDF, bloki lekcji (chord-diagram, caged-shapes,
                     # fretboard-explorer, rhythm-values, progression, tab, ...)
  practice/          # kafelek typu zadania z licznikiem wykonań i przycisk „kolejne
                     # zadanie tego typu" — wspólne dla Matury i Geografii; formularze,
                     # nie linki, bo wydanie zadania bywa mutacją (generuje nowe)
  grammar/lesson/    # renderer bloków lekcji — wspólny dla Linguo i Matury. Bloki
                     # objaśniające (tabela, oś czasu, formuła, porównanie) plus
                     # ćwiczeniowe: fill-gap, match-pairs, order-words, conjugation,
                     # flashcards, key-phrases
  <moduł>/           # komponenty specyficzne dla danego modułu Linguo
lib/
  phoenix/           # rejestr aplikacji + akcje powłoki
  supabase/          # klienci Supabase (przeglądarka / serwer / service role)
  actions/, <moduł>/ # Server Actions per moduł
  ai.ts              # klient Groq + pomocnik do ustrukturyzowanych odpowiedzi JSON
  homework/progress.ts # automatyczne liczenie postępu prac domowych
  matma/             # silnik Matmy: mastery per dział, ocena AI, egzamin,
                     # diagnoza, plan nauki, dashboard, akcje, import CKE
  matura/            # silnik Matury: sekcje, ocena programistyczna środków językowych
                     # (bez AI), ocena AI wypowiedzi pisemnej wg kryteriów CKE, mastery
                     # per część, szacowany wynik, biblioteka teorii (theory.ts),
                     # bank słownictwa (vocab.ts) i powtórki Leitnera (vocab-review.ts);
                     # katalog typów zadań CKE (task-types.ts), kolejka ćwiczeń per typ
                     # (task-stock.ts, writing-stock.ts) i generatory świeżej treści
                     # (generate-tasks.ts)
  grammar/           # typy bloków lekcji (lesson-blocks.ts) + deterministyczne
                     # tasowanie ćwiczeń (shuffle.ts — Math.random rozjechałby hydratację)
  algorytmy/         # Algorytmy: katalog działów i typów zadań, typy bloków lekcji,
                     # kolejka ćwiczeń per typ (exercise-stock.ts) i generator zadań
  godziny/           # Godziny: format czasu/dat i polska odmiana, zapytania
                     # i sumowanie historii, akcje wpisów i tematów
  gitara/            # Gitara: teoria muzyki i kształty akordów (theory.ts, w tym 5
                     # kształtów CAGED wyprowadzonych transpozycją), Web Audio (syntezator
                     # strun Karplus-Strong, metronom z harmonogramem z wyprzedzeniem,
                     # stroik przez autokorelację), typy bloków lekcji, akcje serwerowe —
                     # bez banku zadań (uzasadnienie w migracji 0025 i lib/gitara/actions.ts)
  types/database.ts  # typy TypeScript odzwierciedlające schemat bazy
supabase/
  migrations/        # schemat SQL (0007 = Matma, 0008 = Paragony, 0009 = Schola,
                     # 0013 = Matura, 0016 = wymiar języka, 0017 = teoria i słownictwo,
                     # 0020 = Godziny, 0024 = Algorytmy, 0025 = Gitara)
  seed/               # dane początkowe (admin, słówka, gramatyka, matma/, matura/,
                     # matura-es/, algorytmy/, gitara/)
scripts/
  db.mjs             # runner migracji i skryptów SQL (`npm run db`)
  algorytmy-build-lessons.mjs # walidacja lekcji Algorytmów (JSON) → 03_lessons.sql
proxy.ts             # odświeżanie sesji Supabase + ochrona tras (Next.js 16 "proxy")

Deploy na Vercel

  1. Wypchnij repozytorium na GitHub/GitLab/Bitbucket.
  2. Na vercel.com wybierz Add New → Project i zaimportuj repozytorium (Next.js zostanie wykryty automatycznie, nie trzeba zmieniać ustawień builda).
  3. W Settings → Environment Variables dodaj wszystkie zmienne z sekcji Zmienne środowiskowe (dla NEXT_PUBLIC_SITE_URL wpisz docelowy adres https://twoja-domena.vercel.app).
  4. Wykonaj kroki z sekcji Konfiguracja Supabase, jeśli jeszcze tego nie zrobiono (migracja + seed muszą być uruchomione na tej samej instancji Supabase, na którą wskazują zmienne środowiskowe).
  5. W Supabase, w Authentication → URL Configuration, ustaw Site URL oraz Redirect URLs na adres wdrożenia z Vercela, żeby linki autoryzacyjne działały poprawnie.
  6. Kliknij Deploy. Kolejne pushe do gałęzi produkcyjnej wdrażają się automatycznie.

About

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages