BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
Trening, dieta i aktywności w jednym miejscu.
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @ZdzisiekkkOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
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.Read the full 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).