NBA Feed
팀 뉴스와 경기 정보를 제공, 점수는 직접 확인할 때까지 숨겨져 있습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Mobilna aplikacja webowa (PWA) do prowadzenia treningu siłowego i MMA, diety oraz pozostałych aktywności. Cały interfejs jest po polsku, układ jest zaprojektowany pod telefon trzymany w jednej ręce, a motyw jasny/ciemny przełącza się automatycznie za ustawieniem systemu. Stack: Next.js 16 (App Router) · TypeScript · Tailwind CSS 4 · Supabase (Postgres + Auth + Row Level Security) · recharts · Vercel.README 전문 보기 ↗
Mobilna aplikacja webowa (PWA) do prowadzenia treningu siłowego i MMA, diety oraz pozostałych aktywności. Cały interfejs jest po polsku, układ jest zaprojektowany pod telefon trzymany w jednej ręce, a motyw jasny/ciemny przełącza się automatycznie za ustawieniem systemu.
Stack: Next.js 16 (App Router) · TypeScript · Tailwind CSS 4 · Supabase (Postgres + Auth + Row Level Security) · recharts · Vercel.
source (manual / strava), więc późniejszy import ze
Stravy nie będzie wymagał migracji schematu. Samej integracji w wersji 1 nie ma.src/lib/sleep.ts, nie w bazie - regularność wymaga
porównania z sąsiednimi nocami, a strojenie wag nie ma wymagać migracji.
Baza trzyma wyłącznie fakty.src/lib/health.ts.ANTHROPIC_API_KEY; bez klucza reszta aplikacji działa
normalnie.grind), ustaw hasło do bazy i region Frankfurt (eu-central-1) -
najbliżej Polski.W panelu Supabase otwórz SQL Editor → New query i wykonaj pliki z katalogu
supabase/migrations/ po kolei, każdy jako osobne
zapytanie:
| Plik | Co robi |
|---|---|
0001_schema.sql | tabele, indeksy, triggery, funkcja nadająca rolę admina |
0002_rls.sql | Row Level Security - polityki dostępu dla każdej tabeli |
0003_functions.sql | clone_plan, set_active_plan, widoki i podsumowania |
0004_seed_catalog.sql | 41 ćwiczeń w katalogu, po polsku, z opisem i wskazówkami |
0005_seed_plan_template.sql | plan "Kolano + MMA" jako publiczny szablon (7 dni, 41 pozycji) |
0006_injuries.sql | kontuzje i oceny bólu (zastępują wcześniejszy "ból kolana") |
0007_plan_wlasciciela.sql | plan treningowy właściciela, wygenerowany z plan_treningowy.json |
0008_habits_water.sql | nawyki, odhaczenia i nawodnienie |
0009_todos.sql | listy zadań |
Każdy plik jest idempotentny (if not exists, on conflict do nothing) -
ponowne uruchomienie niczego nie zepsuje.
Zamiast klikać w panelu można puścić wszystko jedną komendą - potrzebny jest
Personal Access Token i ref
projektu (widoczny w adresie panelu):
SUPABASE_ACCESS_TOKEN=sbp_... SUPABASE_PROJECT_REF=twoj-ref npm run db:push
Authentication → Providers → Email: zostaw włączone i wyłącz Confirm email (Authentication → Sign In / Providers → Email → Confirm email).
To nie jest skrót na skróty - wbudowany mailer Supabase wysyła najwyżej 2 wiadomości na godzinę i tylko na adres właściciela organizacji, więc rejestracja oparta o link potwierdzający po prostu nie działa bez własnego SMTP. Z wyłączonym potwierdzaniem konto jest aktywne od razu po rejestracji, bez udziału poczty.
Jeśli kiedyś podepniesz własny SMTP (Project Settings → Authentication → SMTP Settings, np. Resend albo Postmark), możesz potwierdzanie włączyć z powrotem - wtedy zadziała też resetowanie hasła, które jako jedyne nadal wymaga poczty.
git clone <adres-repozytorium> grind-app
cd grind-app
npm install
cp .env.example .env.local
W .env.local wpisz dwie wartości z Project Settings → API:
NEXT_PUBLIC_SUPABASE_URL=https://twoj-projekt.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
npm run dev
Aplikacja stanie na localhost:3000. Załóż konto e-mailem - profil, cele makro i rola tworzą się automatycznie.
Bez tych dwóch zmiennych aplikacja nie wywala się, tylko pokazuje ekran z instrukcją, czego brakuje.
Wypchnij repozytorium na GitHub.
vercel.com/new → Import wybranego repo. Framework (Next.js), komenda budowania i katalog wyjściowy wykryją się same.
W Environment Variables dodaj:
| Zmienna | Wymagana | Skąd |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL | tak | Supabase → Project Settings → API |
NEXT_PUBLIC_SUPABASE_ANON_KEY | tak | tamże, klucz anon public |
ANTHROPIC_API_KEY | nie | console.anthropic.com - tylko dla AI-trenera |
ANTHROPIC_MODEL | nie | domyślnie claude-opus-5 |
Deploy.
Wróć do Supabase → Authentication → URL Configuration i dopisz adres z Vercela do Site URL oraz Redirect URLs.
⚠️
SUPABASE_SERVICE_ROLE_KEYnigdy nie trafia na Vercela ani do repozytorium. Ten klucz omija Row Level Security - jest potrzebny wyłącznie lokalnie, przy jednorazowym imporcie katalogu z wger (niżej).
21 tabel, każda z włączonym Row Level Security. Poza globalnym katalogiem
ćwiczeń i publicznymi szablonami planów każdy widzi wyłącznie własne dane -
sprawdza to zestaw testów (npm run test:db).
| Tabela | Zawartość |
|---|---|
profiles | konto: e-mail, nazwa, rola (user / admin), cele makro, wzrost, rocznik |
exercise_catalog | ćwiczenia: nazwa, opis, wskazówki, błędy, partia, sprzęt, zdjęcie, metryka. user_id IS NULL = pozycja globalna, widoczna dla wszystkich; user_id ustawione = ćwiczenie prywatne |
Hierarchia jest dokładnie taka, jak w założeniach: plan → faza → dzień → ćwiczenie.
| Tabela | Zawartość |
|---|---|
plans | plan użytkownika; is_template + is_public oznaczają szablon do skopiowania |
phases | faza planu (np. "Faza 1 - rehab kolana"), kolejność, opis |
workout_days | dzień treningowy: day_type, tracks_pain (czy po nim pytać o kontuzje) |
workout_exercises | pozycja w dniu: ćwiczenie z katalogu, serie, powtórzenia, przerwa, uwagi |
| Tabela | Zawartość |
|---|---|
workout_sessions | pojedynczy trening: data, dzień planu, start, koniec, czas trwania |
workout_logs | seria: data, ćwiczenie, numer serii, ciężar, powtórzenia, czas, dystans, RPE, rozgrzewkowa czy robocza |
injuries | kontuzja: nazwa, część ciała, strona, status (aktywna / obserwacja / wyleczona), od kiedy, notatka, czy pytać o ból po treningu |
pain_logs | ocena bólu 0-10 dla konkretnej kontuzji, z notatką - jedna na kontuzję i dzień |
body_weight_logs | pomiar wagi ciała |
| Tabela | Zawartość |
|---|---|
foods | produkt: makro na 100 g, porcja, marka, zdjęcie, off_id dla pozycji z Open Food Facts |
meals | posiłek danego dnia (Śniadanie / Obiad / Kolacja / Przekąska) |
meal_entries | pozycja w posiłku: gramatura + makro liczone automatycznie kolumnami generowanymi w bazie |
| Tabela | Zawartość |
|---|---|
activities | aktywność: typ, czas, dystans, kalorie, source (manual / strava) |
habits | nawyk: nazwa, ikona, cel dzienny, dni tygodnia, godzina przypomnienia |
habit_logs | odhaczenie nawyku - jeden wiersz na nawyk i dzień, z licznikiem |
water_logs | pojedynczy wpis wody w ml (osobne wpisy, żeby dało się cofnąć jeden) |
todo_lists | lista zadań: nazwa, ikona, kolejność |
todos | zadanie: treść, notatka, termin, priorytet, moment odhaczenia |
sleep_logs | jedna noc: godziny, czas zasypiania, pobudki, ocena, energia rano, czynniki. time_in_bed_min to kolumna generowana licząca różnicę przez północ |
ai_plan_requests | historia zapytań do AI-trenera wraz z wygenerowanym planem |
| Nazwa | Do czego |
|---|---|
clone_plan(plan_id, nazwa, aktywuj) | kopiuje cały plan z fazami, dniami i ćwiczeniami na konto wywołującego |
set_active_plan(plan_id) | ustawia jeden plan jako aktywny |
last_exercise_sets(...) | serie z ostatniego treningu danego ćwiczenia - to, co widać obok pól wpisywania |
period_summary(od, do) | podsumowanie okresu: treningi, serie, objętość, kcal, aktywności, waga, ból, woda, sen oraz mianowniki potrzebne Health Score (habit_days_due, days_in_period) |
sleep_factor_keys() | zamknięta lista czynników snu - baza waliduje nią kolumnę factors |
v_daily_nutrition | makro zsumowane per dzień |
v_daily_volume | objętość i liczba serii per dzień |
v_exercise_prs | rekordy dla każdego ćwiczenia |
v_daily_water | wypite mililitry per dzień |
v_sleep | noc z policzonym realnym snem (czas w łóżku minus zasypianie i minuty na jawie) |
Widoki mają security_invoker = on, więc nie omijają Row Level Security.
Migracja 0001_schema.sql nadaje rolę admin kontu założonemu na adres
[email protected] - automatycznie, w momencie rejestracji.
Administrator dodatkowo może edytować i usuwać pozycje w globalnym katalogu
ćwiczeń oraz publikować plany jako szablony. Żeby zmienić ten adres, popraw go
w funkcji public.handle_new_user() zanim uruchomisz migrację.
Roli nie da się nadać sobie samemu z aplikacji - polityka profiles_update_own
wprost blokuje zmianę kolumny role przez użytkownika.
Dorzuca ~120 ćwiczeń ze zdjęciami z wger.de do globalnego katalogu (ręcznie opisane 41 pozycji zostaje na wierzchu).
# w .env.local, tylko lokalnie:
SUPABASE_SERVICE_ROLE_KEY=eyJ...
WGER_DRY_RUN=1 npm run import:wger # podgląd, nic nie zapisuje
npm run import:wger # właściwy import
Skrypt jest idempotentny (on conflict (source, source_id)), więc można go
uruchomić ponownie. Po imporcie usuń service role key z .env.local.
| Komenda | Co robi |
|---|---|
npm run dev | serwer deweloperski |
npm run build | build produkcyjny |
npm run lint | ESLint + reguły React Compilera |
npm run validate:sql | uruchamia wszystkie migracje w PGlite (Postgres w WASM) - łapie błędy SQL bez stawiania bazy |
npm run test:db | 15 testów schematu i Row Level Security: izolacja danych między kontami, rola admina, kopiowanie planu, liczenie makro, podsumowania |
npm run test:wstecz | 30 sprawdzeń wpisywania wstecz: okno siedmiu dni, passa po dopisaniu zaległego dnia, zapis z datą wsteczną w bazie |
npm run db:push | uruchamia wszystkie migracje na zdalnym projekcie Supabase (wymaga SUPABASE_ACCESS_TOKEN i SUPABASE_PROJECT_REF) |
npm run test:live | test end-to-end na żywym wdrożeniu: rejestracja, logowanie, wszystkie ekrany, skopiowanie planu, zapis serii, podsumowanie - z posprzątaniem po sobie |
npm run verify:plan | sprawdza, czy plan w bazie zgadza się co do znaku z plan_treningowy.json |
npm run import:wger | import katalogu z wger (wymaga service role key) |
npm run icons | generuje ikony PWA do public/icons/ |
validate:sql i test:db nie potrzebują Dockera ani zainstalowanego Postgresa -
działają na PGlite.
test:live uderza w prawdziwe wdrożenie - zakłada konto testowe, przechodzi całą
ścieżkę użytkownika i kasuje je na końcu:
GRIND_URL=https://twoja-apka.vercel.app \
NEXT_PUBLIC_SUPABASE_URL=https://twoj-ref.supabase.co \
NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_... \
SUPABASE_SERVICE_ROLE_KEY=... \
npm run test:live
license, license_author i license_url i wyświetlane na karcie ćwiczenia.source, nie ma OAuth).