SkillSync AI
A learning planner that turns a goal like "learn Python" into a timetable that fits the hours a person actually has — then keeps it honest as real life moves things around.

Overview
A learning planner that turns a goal like "learn Python" into a timetable that fits the hours a person actually has — then keeps it honest as real life moves things around.
- Generates personalised timetables that fit a user's stated daily schedule.
- Milestone tracking, streaks and auto-rescheduling when sessions slip.
- Google Calendar sync, email reminders via Brevo, and offline PWA support.
The problem
Most learning plans fail on scheduling, not motivation. Generic course roadmaps assume free evenings that learners do not have, so the first missed session collapses the whole plan and there is no mechanism to recover.
Who it is for
Self-directed learners studying around a job or a degree, who need a plan shaped around their real week.
My responsibilities
- Built the full application: schedule modelling, plan generation, persistence and UI.
- Designed the prompt and generation flow that turns a goal plus a stated routine into a milestone-based timetable.
- Implemented Google Calendar sync, Brevo email reminders, streak tracking and PWA offline support.
- Modelled users, plans, milestones and progress in Supabase/PostgreSQL.
Product & technical decisions
The model plans; the app owns the schedule
The LLM is good at decomposing a goal into milestones and bad at being a source of truth. Generated plans are persisted as structured rows in PostgreSQL, so rescheduling, streaks and progress are computed by application logic — deterministic and inspectable — not re-asked of the model.
Supabase for auth, database and storage together
One managed service covering Postgres, authentication and row-level security removed a whole class of glue code and let the schema carry the access rules.
Meet users in their existing calendar
A plan that lives only inside its own app gets forgotten. Calendar sync plus email reminders puts sessions into tools the learner already checks daily.
PWA over native
Installability and offline access were the only mobile-specific requirements, and a PWA delivers both from the same Next.js codebase.
Architecture
How the pieces fit together, from the surface the user touches down to the sources of truth.
Client
- Next.js app
- PWA shell
Server
- Route handlers
- Plan generator
- Scheduler
Data
- Supabase Auth
- PostgreSQL
Integrations
- Gemini AI
- Google Calendar
- Brevo email
InterfaceApplication logicData & authThird-party
Key functionality
Schedule-aware plan generation
The user describes their real routine and picks a goal; Gemini generates a timetable that fits the gaps, broken into milestones with suggested resources rather than one undifferentiated wall of topics.
Auto-rescheduling
Missing a session rewrites the plan forward instead of leaving the learner behind a plan they can no longer follow — the failure mode that kills most study schedules.
Calendar sync and reminders
Sessions push into Google Calendar so the plan lives where the user already looks, with Brevo handling automated email nudges.
Streaks and progress
Milestone completion and streak tracking give the plan a feedback loop, so progress is visible rather than assumed.
Installable and offline-capable
Built as a PWA so the plan is reachable on a phone without a connection.
What went wrong, and what I did
An auth state boundary between Supabase and the client store
- Constraint
- Google OAuth created a valid Supabase session, but the client-side Zustand store stayed empty after the callback. The auth provider and the interface could therefore disagree about whether someone was signed in.
- Wrong turn
- My first callback handled the OAuth code in a Next.js server route and redirected straight to the dashboard. The Supabase exchange succeeded, but a server route has no way to populate browser state — so the protected UI loaded before it knew who the user was.
- What I shipped
- Replaced the server-only callback with a client callback page that reads the authorization code, calls
exchangeCodeForSession, falls back togetSession, writes the authenticated user into Zustand, and only then redirects — returning users to login with an explicit error when any step fails. - Effect
- Sign-in now lands in the dashboard with the Supabase session and the application state established together, instead of briefly treating a successfully authenticated user as logged out.
Where it stands
SkillSync AI is deployed and publicly usable — the full feature set above is live rather than a prototype.
What I would improve next
- Let learners edit a generated plan directly and have the scheduler respect the edit.
- Spaced-repetition review sessions layered onto the milestones.
- Shared plans so two people can study the same goal in parallel.