All projects

Extracurricular

A directory where parents in Canada search for children's extracurricular programs and businesses list them, built as a React + TypeScript single-page app on Firebase. I joined an existing codebase to fix bugs and tighten typing.

Role
Contributor on an existing codebase, frontend only. The app was written by another developer; I stabilised it with bug fixes and typing clean-up. I wrote 3 of the 25 commits.
Timeline
April 2024 (bug-fix contribution to a codebase started in May 2022)
4 bug fixes shipped: review form, website links, service phone number, login redirect
6 Firestore collections: users, categories, children, locations, services, reviews
25 commits in the repo, 3 of them mine (9–10 April 2024)

Overview

Extracurricular is a web directory where parents in Canada find activity programs for their children, such as sports, arts, coding and academic classes. Businesses register and list their services. The original app was written by another developer. I joined in April 2024 to stabilise it: I fixed the review form, the website links on listings, the phone number shown on a service page, and the login redirect, and added explicit TypeScript types to several files.

Goals

  • Let parents search and filter children's activities by category, city, age group, timing and format
  • Let providers register a business, add locations, and publish service listings with photos
  • Let parents save favourites, manage child profiles and review programs

Tech stack

React 18TypeScriptViteRedux ToolkitReact Router 6Firebase AuthenticationCloud FirestoreFirebase StorageGoogle Maps JavaScript APITailwind CSSMaterial UIFlowbiteReact Hook FormESLint (Airbnb config) + Prettier + HuskyVercelVitestDay.jsReact-ToastifyGoogle Places autocomplete

Key features

  • Parents and businesses register through separate sign-up flows, with email verification before they can log in
  • Visitors browse a home page with activity category cards and a search box
  • A service list view filters programs by category, city, age group (preschool to high school), format, type and timing
  • Each program has a detail page with an overview, seller information, a Google Map, and the provider's website and phone number
  • Logged-in parents can submit reviews on a program and save favourites
  • Parents can add and manage child profiles in settings
  • Businesses manage their account, locations and services in a protected settings area, including photo uploads
  • Locations are entered with Google Places autocomplete, and a distance calculation helper exists in the code
  • The service-creation form offers a large list of Canadian place names as a pick list

Challenges & solutions

Problem

The review form depended on user.favorites existing on the signed-in user, so it could fail for users who had no favourites field.

Solution

I removed that requirement so the form works without it.

Problem

The service detail page showed the owner's main phone number instead of the phone number saved on the listing.

Solution

The page now shows the service's own phoneNumber.

Problem

Providers often entered a website without a protocol, so the 'visit website' link on the detail page was treated as a relative path and went nowhere.

Solution

The link now checks for the protocol and adds https:// if it is missing.

Problem

After logging in, the app navigated client-side, which I took to be leaving some parts of the app with stale state.

Solution

I replaced navigate('/') with a full page redirect to / after login. This is a workaround rather than a state fix, and the code still has a commented-out window.location.reload() beside it.

Lessons learned

  • A full-page redirect hides a state problem, it doesn't solve it. The better fix is to find out which state is read once at startup and make it reactive.
  • Public client keys are normal for Firebase, but they only stay safe if Firestore security rules and authorized domains are set properly. A Google Maps key needs a domain restriction.

Known limitations & next steps

  • An old Firebase key and a Google Maps key appear in the repo's git history, and the Maps key is still hard-coded in index.html. The Maps key should be domain-restricted or rotated. The current configuration reads keys from a gitignored environment file.

Screenshots

Extracurricular screenshot

Want something like this built?

Tell me about your project and I'll get back to you.

Get in touch
Next project LMS Web App for Mr. Essam Mathematics