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/gramatykai/matura/nauka/slownictwo), zbudowana w innej sesji. Została wycofana migracją0022, bo nie miała wymiaru języka — jej tabele nie mają kolumnylanguage, 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.
⚠️ Migracja0015w 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 numer0016, nie0015. 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).
- Stack technologiczny
- Funkcje
- Uruchomienie lokalne
- Konfiguracja Supabase
- Zmienne środowiskowe
- Konto administratora
- Testy end-to-end
- Struktura projektu
- Deploy na Vercel
- 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.tsnaproxy.ts(patrzproxy.tsw katalogu głównym) — jeśli coś aktualizujesz w oparciu o starsze przykłady z internetu, uwzględnij tę zmianę.
- 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.
- 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.
- Ś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.
- 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).
- Łą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ą.
- Gramatyka — tematy per poziom z wyjaśnieniami po polsku, ćwiczenia (luki, wybór, przekształcenia zdań oceniane przez AI).
- Czytanie — AI generuje krótkie artykuły w wybranym języku, dopasowane do poziomu i tematu, zadaje pytania (ABCD + otwarte), ocenia odpowiedzi otwarte.
- 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.
- 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.
- Słuchanie — wklejasz link do YouTube, aplikacja pobiera transkrypcję i tworzy ćwiczenie z lukami; kliknięcie luki przewija film do właściwego momentu.
- 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.
- Kalendarz i streaki — kalendarz miesięczny z oznaczonymi dniami aktywności, aktualny streak i rekord, zbiorcze statystyki.
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 devAplikacja wystartuje na http://localhost:3000.
-
Utwórz nowy projekt na supabase.com.
-
W SQL Editor uruchom po kolei zawartość plików z katalogu
supabase/(albo z terminala — patrz Wgrywanie migracji z terminala):Migracje (schemat):
supabase/migrations/0001_init.sql— schemat bazy (tabele, enumy, RLS, funkcje).supabase/migrations/0002_learning_path.sql— tabela ścieżki nauki (etapy per poziom).supabase/migrations/0003_multilang_homework_matching.sql— wielojęzyczność (kolumnalanguage+profiles.target_language), prace domowe per-uczeń, gra „łączenie tłumaczeń", polityki RLS admin-read (dzięki nim admin widzi postęp uczniów).supabase/migrations/0004_writing_tasks_insert_own.sql— polityka RLS pozwalająca uczniom generować zadania pisemne.supabase/migrations/0005_phoenix_installed_apps.sql— kolumnainstalled_apps(aplikacje widoczne na launcherze Phoenixa).supabase/migrations/0006_prompt_forge.sql— tabelaprompt_sessions(Kuźnia: sesje kreatora promptów).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 Storagemath-attemptsna zdjęcia brudnopisu.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 cenetf_price_history(bez RLS per-user — patrz komentarz w migracji); tworzy też prywatny bucket Storageparagony-receiptsna zdjęcia paragonów.supabase/migrations/0009_schola.sql— schemat Scholi (osobny realm, patrz wyżej):schola_members(osobne członkostwo, niezależne odprofiles),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).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).supabase/migrations/0014_matura_writing.sql— schemat „Wypowiedzi pisemnej":matura_writing_tasks(bank zadań z wzorcową odpowiedzią) imatura_writing_submissions(oceniane analitycznie przez AI wg 4 kryteriów CKE, patrz opis aplikacji wyżej) — osobne tabele odmatura_tasks/matura_task_attemptsz 0013, bo ocena jest holistyczna, nie dopasowaniem pojedynczych odpowiedzi.supabase/migrations/0020_matura_language.sql— wymiar języka w Maturze: kolumnalanguagewmatura_sectionsi w tabelach per-użytkownik, które trzymają poziom bezsection_id. Wszystko, co wisi nasection_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.supabase/migrations/0021_matura_theory.sql— biblioteka teorii i bank słownictwa:matura_lessonsdostajeslug(własny adres lekcji),summary,kind(gramatyka/słownictwo/strategia) i szacowany czas; dochodzimatura_lesson_progress(znacznik „przerobione") orazmatura_vocab_topics/_entries/_progress(bloki tematyczne, hasła, powtórki na pudełkach Leitnera). Osobne tabele odvocabulary_wordsz 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.slugjestNOT NULL, więc seedy lekcji trzeba uruchomić po tej migracji.supabase/migrations/0023_matura_task_types.sql— typ zadania CKE na każdym wierszumatura_tasks(kolumnatask_type), czyli oś, wokół której ćwiczy się zamiast ponumerowanej listy. Klasyfikacja siedzi w funkcjimatura_infer_task_type(polecenie + kształt itemów) i w triggerzeBEFORE INSERT/UPDATE, a nie w jednorazowymUPDATE— seedy kasują i wstawiają swoje wiersze przy każdym uruchomieniu, więc jednorazowy backfill zgubiłby klasyfikację przy najbliższymnpm run db seed. Reguły sprawdzono na kompleciesupabase/seed/matura/imatura-es/: każde zaseedowane zadanie trafia we właściwy typ. Wypowiedź pisemna nie dostaje kolumny — jej typem jestform_type, ta migracja tylko poszerza dopuszczalne wartości oartykulilist_formalny. Numer0023sprawdź przeznpm run db statusprzed wgraniem — patrz ostrzeżenie o kolizjach numeracji wyżej.supabase/migrations/0024_algorytmy.sql— schemat aplikacji Algorytmy:algo_topics,algo_lessons+algo_lesson_progress,algo_exercises(bank jednokrotnego wyboru ztask_typeNOT NULL od początku — w przeciwieństwie do Matury, gdzie kolumnę trzeba było dołożyć do istniejącego banku) orazalgo_exercise_attempts. Politykaalgo_exercises_insert_owndopuszcza wiersz, któregocreated_byto wołający — dzięki temu kolejka ćwiczeń dogenerowuje zadania bez klucza service-role, dokładnie tak jakgeo_exercises. Ten sam warunek:npm run db statusprzed 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.sql…01_vocabulary_b2.sql— słownictwo EN (~1000 słówek). 10.02_grammar_a1.sql…02_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.sql…es_01_vocabulary_b2.sql,es_02_grammar_a1.sql…es_02_grammar_b2.sql, a na końcues_03_learning_path.sql.Seed — rosyjski (opcjonalnie, jeśli chcesz język RU): 13.
ru_01_vocabulary_a1.sql…ru_02_grammar_b2.sql, a na końcuru_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).
supabase/seed/matma/02_lessons_<dzial>.sqli03_problems_<dzial>.sql(po jednej parze plików na dział, 11 par) — interaktywne lekcje i bank zadań (źródłotopic). Uruchom01_topics.sqlprzed nimi (odwołują się do działów poslug).- Prawdziwe zadania maturalne CKE (
source: 'past_exam') nie są w plikach seed — importuje je administrator jednorazowym skryptem z panelu/matma/admin/import(patrzlib/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) i17_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 formacieGrammarBlock— ten sam renderer co lekcje gramatyki w Linguo, poszerzony w 0017 o bloki ćwiczeniowe. Uruchom01_sections.sqlwcześniej. 19.supabase/seed/matura/03_tasks_srodki_jezykowe.sql— kuratorowany bank zadań (source: 'curated'), po 3 zadania na poziom. Uruchom01_sections.sqlwcześ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 zlib/matura/writing-grading.ts, który tymi samymi kryteriami karmi oceniające AI. Uruchom01_sections.sqlwcześniej. 21.supabase/seed/matura/05_writing_tasks_podstawowa.sqli06_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ź. Uruchom01_sections.sqlwcześniej. 22.supabase/seed/matura/07_lessons_czytanie.sqli08_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ścikind='strategia', bo w tym dziale punkty traci się na metodzie, nie na języku. Uruchom01_sections.sqlwcześniej.
supabase/seed/matura/09_lessons_sluchanie.sqli10_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. Uruchom01_sections.sqlwcześniej.supabase/seed/matura/11_vocab_topics.sql— 15 bloków tematycznych zakresu z podstawy programowej. Uruchom przed plikami12–16, które szukają bloku poslug. 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.supabase/seed/matura/12_vocab_*.sql…16_vocab_*.sql— 425 haseł angielskich, po trzy bloki na plik. Kolumnanoteniesie to, czego para hasło–tłumaczenie nie unosi, a co realnie decyduje o punktach: niepoliczalność (homework,luggage,research), kolokacje (takevspass an exam,dovsmake 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 migracji0020_matura_language.sql. 26.matura-es/01_sections.sql— te same 4 części × 2 poziomy, tym razem zlanguage = '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) i03_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 oznaczonesource: 'curated'(niepast_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.sqli08_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.sql— tylko lekcje (5), bez zadań. Zadanie ze słuchu wymagacontent.youtubeVideoIdwskazują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 samymislug, żeby uczeń przełączający język trafiał na ten sam blok, a nie na inny. Uruchom przed plikami12–16. 32.matura-es/12_vocab_*.sql…16_vocab_*.sql— 513 haseł hiszpańskich. W kolumnienoteto, na czym Polacy realnie tracą punkty:el pelow liczbie pojedynczej mimo polskiej mnogiej,las gafaszawsze w mnogiej,caer bienze składnią jakgustar,el mapaiel problemarodzaju męskiego mimo końcówki-a, oraz fałszywi przyjaciele w rodzajuembarazada.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.sqlwymaga 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.sqltego języka, żeby odtworzyć ścieżkę. -
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).
-
Skopiuj Project URL, anon public key i service_role key z Project Settings → API do
.env.local.
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/postgresnpm 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 0001–0009 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_URLzawiera 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.
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.
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ąadminw tabeliprofiles.
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 interaktywnySzczegóły (co jest pokryte, jak działają jednorazowe konta testowe) w e2e/README.md.
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")
- Wypchnij repozytorium na GitHub/GitLab/Bitbucket.
- Na vercel.com wybierz Add New → Project i zaimportuj repozytorium (Next.js zostanie wykryty automatycznie, nie trzeba zmieniać ustawień builda).
- W Settings → Environment Variables dodaj wszystkie zmienne z sekcji
Zmienne środowiskowe (dla
NEXT_PUBLIC_SITE_URLwpisz docelowy adreshttps://twoja-domena.vercel.app). - 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).
- 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.
- Kliknij Deploy. Kolejne pushe do gałęzi produkcyjnej wdrażają się automatycznie.