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.
Build the next generation of footballers through structured training and digital player passports.
Sports & fitnessTypeScript · PLpgSQLGitHub @madlalakhaya25OnlineOwner 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
Grassroots football platform for player development, team management, and talent discovery. Built for African football ecosystems.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
A grassroots football platform for player development, team management, and talent visibility, built for Growfit Sports Academy (Greater Durban, an NPC) and designed so other South African academies can run on it too. Coaches, players, parents and admins each get a home screen made for the job they do that day.
Every screen shows the academy's own name and crest. Pages with several areas use URL tabs (?tab=), so a tab can be bookmarked or shared (lib/tabs.ts, QueryTabs).Read the full README ↗A grassroots football platform for player development, team management, and talent visibility, built for Growfit Sports Academy (Greater Durban, an NPC) and designed so other South African academies can run on it too. Coaches, players, parents and admins each get a home screen made for the job they do that day.
| Role | Core capability |
|---|---|
| Coach | Squads, fixtures, training and attendance; the tactics board; playing-time planner; term reviews; a squad-aware AI assistant |
| Player | A Today home and a Passport (position and role, attributes, ratings), plays and homework from the coach, skill challenges, development milestones |
| Parent | A Today home for their own child (next match or training, forms to sign, the coach's weekly note), a weekly family digest, digital document signing |
| Admin | Today home with registration health, teams to chase and welfare count; academy-wide players, teams, drills, term dates, analytics, SAFA document compliance |
Every screen shows the academy's own name and crest. Pages with several areas use URL tabs (?tab=), so a tab can be bookmarked or shared (lib/tabs.ts, QueryTabs).
ai_analysis_consent).A pitch-diagram animation studio, built to match dedicated tools like The Tactics App and Final Third:
PRESETS_APPROVED in lib/attribute-presets.ts)BAND_DESCRIPTIONS_APPROVED in lib/term-review.ts)Gemini only, grounded in FIFA LTPD, the 4-Corner Model, SAFA NDP and CAF youth principles. It covers the session planner, player insights, development plans, match and parent reports, the academy health report, tactical explainers, opponent analysis, board instructions, drill diagrams, weekly family digest and a conversational coach assistant that suggests an XI and writes match plans.
It reads the academy's own data (ratings, form, attendance against the 75% policy, results) so advice names real players, and it is constrained not to invent players or statistics. Results are stored (ai_artefacts), cached, rate limited, and retried with an optional fallback model (GEMINI_MODEL_FALLBACK). AI use is tracked per month on the admin analytics page.
| Layer | Technology |
|---|---|
| Web frontend | Next.js 16 (App Router, async searchParams), React 19, Tailwind CSS v4 |
| Database | Supabase (PostgreSQL) with Row Level Security |
| Auth | Supabase Auth, email + password |
| AI | Google Gemini via @google/genai |
| Documents and media | pdf-lib (handouts, cards), mediabunny (MP4 export) |
| Validation | Zod v4 |
| Errors | Sentry (@sentry/nextjs, EU region) |
| Tests | Jest (unit), Playwright (smoke) |
| Deployment | Vercel (web, main branch only) |
growfit/
├── web/ # Next.js web application
│ ├── src/
│ │ ├── app/
│ │ │ ├── (protected)/dashboard/
│ │ │ │ ├── admin/ # Today, players, teams, drills, development, analytics, academy
│ │ │ │ ├── coach/ # Squad, fixtures, training, tactics, assistant, welfare, settings
│ │ │ │ ├── player/ # Today + Passport tabs, development, homework, challenges, tactics
│ │ │ │ └── parent/ # Today, child detail, fixtures, announcements, settings
│ │ │ ├── actions/ # Server Actions, one file per domain
│ │ │ ├── auth/ # Login, register, password reset, role picker
│ │ │ └── passport/ # Public player passport (no auth)
│ │ ├── components/ # Shared UI (ui/ holds the design primitives)
│ │ └── lib/ # Pure helpers with tests in lib/__tests__
│ │ ├── *-data.ts # Loaders that read through the user's own session, so RLS applies
│ │ ├── board-*.ts # Tactics board model, instructions, timeline, video, render
│ │ ├── ai-*.ts # Gemini guard, cache, retry, safeguards, artefacts
│ │ ├── tabs.ts # URL tabs
│ │ └── supabase/ # Server and browser clients
├── supabase/migrations/ # 001 to 066 (046 and 047 were never used)
├── site/ # Public marketing site
└── docs/ # See Further reading
git clone https://github.com/madlalakhaya25/growfit.git
cd growfit/web
npm install
Copy web/.env.example to web/.env.local.
| Variable | Needed | Purpose |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY | Yes | Supabase project |
NEXT_PUBLIC_SITE_URL | Yes | Absolute links for shared passports and plays |
GEMINI_API_KEY | For AI | Every AI feature |
GEMINI_MODEL, GEMINI_MODEL_DOC, GEMINI_MODEL_LITE, GEMINI_MODEL_FALLBACK | Optional | Override model ids (defaults in src/lib/ai-models.ts) |
SENTRY_DSN, NEXT_PUBLIC_SENTRY_DSN | Optional | Error reporting |
SENTRY_AUTH_TOKEN | Optional | Readable production stack traces |
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN | Optional | Shared rate limiting (falls back to in-memory) |
Run every file in supabase/migrations/ in numerical order, 001_schema.sql through 066_player_positions.sql, in the Supabase SQL Editor (or supabase db push). Migrations are idempotent. The app tolerates a missing table or column, so a feature simply stays empty until its migration has run.
Migrations 030 onward are described, with verification queries, in docs/MIGRATION_RUNBOOK.md. Run any migration that changes policies or data on production deliberately, not as part of a deploy.
Then insert a seed academy (or register one at /register-club):
INSERT INTO academies (id, name, location, province)
VALUES ('00000000-0000-0000-0000-000000000001', 'Growfit Sports Academy', 'Greater Durban', 'KwaZulu-Natal')
ON CONFLICT (id) DO NOTHING;
supabase/seed.sql seeds a fuller test project.
In Authentication → Providers: enable Email, disable confirmation for a pilot (or configure SMTP), set Site URL to http://localhost:3000, and allow http://localhost:3000/api/auth/callback as a redirect URL.
cd web
npm run dev # http://localhost:3000
npm test # Jest
npm run test:e2e # Playwright smoke tests
npm run build
The web app deploys to Vercel from main only. web/vercel.json sets an ignoreCommand so every other branch is skipped, which means pull requests get no preview URL; verify visuals locally. Set the environment variables above in the Vercel project settings.
CI (.github/workflows/pr-checks.yml) runs tests and the build on every pull request, alongside CodeQL, SonarCloud and GitGuardian. Commit messages must not carry AI co-author trailers.
See docs/ARCHITECTURE.md for the full design.
"use client" is for interactive piecesapp/actions/. A "use server" file exports only async functions, and a test guards that*-data.ts loaders use the user's own session so a query can only return what that user may seelib/: rules (attendance, playing time, board instructions, Today homes) are plain functions with unit tests, separate from the loaders that fetch data