wanessalabs standalone production

TutorHub

A web app for running an independent tutoring practice: scheduling, Google Calendar sync, a smart task list, and Venmo payment requests.

ViteReact 19TypeScriptTailwind CSS v4SupabaseHonoCloudflare Pages FunctionsVitest

A web app for running an independent tutoring practice: students, sessions, topics, Google Calendar sync, and Venmo payment requests, all in one place. Built for a single tutor, not a multi-tutor org, that constraint is intentional and keeps the data model simple.

What It Is

TutorHub replaces the paper calendar and text-thread version of running a tutoring business. A tutor signs in, connects their Google Calendar, and gets a smart calendar view that overlays real events with tutoring sessions, color-coded by status. A dashboard tracks earnings and hours with month-over-month trend indicators. A task list generates itself from the data: students without an upcoming session, sessions starting soon that need a reminder, completed sessions still unpaid after 48 hours. Tasks resolve themselves when the underlying condition clears.

Built in Phases

Auth (Google OAuth and email/password), the Google Calendar integration, the dashboard, and the smart task list were built first and live-verified against a real Supabase project and Google Cloud OAuth client, not just tested locally with mocks. Student management, a multi-calendar overlay, per-student booking links (a public self-serve page with Cloudflare Turnstile and a database exclusion constraint that makes double-booking impossible), Venmo payment requests, and filter-aware spreadsheet export followed, each live-verified the same way and with security-auditor passes on the payment and public surfaces. All eight phases are built and live-verified against the real backend, and the app is deployed on Cloudflare Pages. Google login, calendar sync, booking, payments, and export were each confirmed working on the live deployment. It runs at tutorhub.wanessalabs.com.

The Design System Pass

Once the core phases worked, the visual layer got a dedicated overhaul: a warm, personal design direction instead of generic SaaS, run through a full brainstorm-to-spec-to-plan-to-execution pipeline with a final whole-branch review before merging. New primitives (status badges, empty states, loading skeletons) replaced the placeholder emoji-based badges from the early build. Four more rounds followed: a day-detail view for the calendar, task urgency indicators, a password visibility toggle, and settings polish, each shipped as a small, independently tested change directly to the main branch.

Honest Constraints

Venmo has no public confirmation API, so marking a payment as received is a manual step by design, not an oversight. The single-tutor scope means no admin roles or shared accounts. And the visual pass has been verified by automated tests and builds, but not yet by a human clicking through the app in a browser, that check is still pending.

Stack

LayerToolRole
FrontendVite + React 19 + TypeScriptStrict mode, no any
StylingTailwind CSS v4Custom design tokens, no component library dependency
DataSupabase (Postgres, Auth, RLS)Row-level security on every table, scoped to the signed-in tutor
APIHono on Cloudflare Pages FunctionsGoogle tokens and secrets stay server-side only
TestingVitest76 tests, all pure logic and rendering behavior

Development timeline

11 logged updates over 24 days, 7 Jul 2026 to 30 Jul 2026.

  1. Correction: the custom domain was recorded under the wrong hostnamefix

    That host has never resolved: a browser check on 2026-07-30 returned ERR_NAME_NOT_RESOLVED. The registered Cloudflare Pages custom domain on project tutorhub is tutorhub.wanessalabs.com, which returns 200 and serves the app.

  2. Launch-readiness pass (NO-GO to GO pending redeploy)feature

    The Privacy Policy carries the Google API Services User Data Policy Limited Use disclosures (scopes calendar.events + calendar.calendarlist.readonly, secure server-side token storage, no ads / no sale / no model training, revoke path)…

  3. Entire remaining build (Phases 5-8) + Google OAuth fixes + multi-calendarfix

    Single session, every feature brainstorm → spec → plan → TDD → live-verify. All commits to main by explicit path (shared branch).

  4. design/ folder added (canonical brand + tokens)feature

    No invented values. bespoke --radius-card (16px), the lucide status vocabulary, and the six signature components.

  5. App-shell refinement (fifth round) + docs/portfolio catch-updocs

    Nav links highlight the current route (text-primary font-medium); below sm, the flat 4-link row collapses behind a hamburger toggle expanding into a vertical menu (including Sign out) instead of wrapping.

  6. Live verification (Phases 1-4)feature

    Clemens created the Supabase project (wanessalabs account) and Google OAuth client; filled .env and .dev.vars.

  7. Post-overhaul UI/UX refinement rounds (four commits, same session)feature

    Once the 16-task overhaul merged, continued iterating directly on main (small, well-scoped features, no separate branch/plan needed) — brainstormed each round conversationally with AskUserQuestion menus, then built with TDD where the…

  8. UI/UX overhaul (design → plan → subagent-driven-development → merge)featureunverified

Show the earlier 3 entries
  1. Kickoff + Phase 1 scaffoldfeature

    Confirmed with Clemens: vault canon instead — Vite + React + TS strict + Tailwind v4, Hono on Cloudflare Pages Functions, Supabase, Vitest.

  2. Phase 2 build (same session)feature

    Server (Hono on Pages Functions): /api/google/oauth/start + /callback (HMAC-signed state carries user id statelessly, 10-min TTL), /api/google/disconnect (revoke + delete + flag flip), /api/google/events (refresh-token → access-token →…

  3. Phases 3 + 4 build (same session, continued on user go-ahead)feature

    Phase 3 (dashboard): stat cards + earnings-by-month bar / hours-by-week line (recharts). Chart chrome per the dataviz skill (validated series color #2a78d6, hairline grid, muted ink, tooltips, no legend for single series).

Written from this project's decision log as work happened, not afterwards. 1 entry was withheld from publication. See every project →