← all work

community platform · 2025

KJRC

The official platform for Kelana Jaya Run Club, combining a race-day editorial website with verified member profiles, events, merch, and admin tools.

visit site

Most club websites stop at a homepage, a schedule, and a gallery.

KJRC needed those things, but it also needed a proper digital home for the club to operate.

I started with the public-facing website: training schedules, running divisions, athletes, events, gallery, merchandise, and the KJRC Games experience. The first version landed in December 2025. Since then, it grew into something closer to a community platform.

From roster to member profile

The interesting problem was what happens after someone joins.

KJRC already had an official membership list, but members did not have a way to claim their own public identity. I built a verified claim flow that lets members confirm their membership privately using their membership number and registered phone number.

The flow became:

Verify membership → create an account → choose a username → publish a profile

Behind the scenes, the system uses server-side fingerprints, short-lived claim tokens, rate limits, protected routes, and Supabase authentication. The original membership data stays private while the member gets a public profile at:

kjrc.my/username

Members can add a bio, location, running interests, social links, achievements, affiliations, sponsorships, profile images, and visual preferences.

A public directory that feels alive

The member system is not just a private portal.

Public profiles can be discovered through a searchable member directory with filters, sorting, pagination, division information, and sponsored athlete labels.

Each profile is a real page, not just a row in a database. Members can share their profile directly, and the site generates custom Open Graph cards for each person.

That meant building more than a frontend view. Cloudflare middleware detects crawler requests and injects the correct metadata, while an edge function generates profile cards as SVG images. I also added emoji font handling so profile names and interests render consistently in social previews.

The admin side matters too

Community websites usually have an invisible operational layer.

For KJRC, I built an admin surface for importing membership data from CSV files, previewing accepted and rejected rows, handling conflicts, downloading error reports, and confirming partial imports.

Admins can also manage official affiliations, committee roles, sponsorships, profile moderation, and member media.

Uploaded images are placed into quarantine, validated, resized, converted, and moved into controlled storage. The supporting database policies and edge functions handle the permissions and lifecycle around that data.

Designing for a real community

The visual direction evolved into a boxy, race-day editorial identity.

The site uses bold typography, monochrome surfaces, topographic textures, strong borders, responsive layouts, and small motion details that make the experience feel active without getting in the way.

The goal was not to make KJRC look like a generic running club website.

It needed to feel like the club itself: energetic, organised, slightly rough around the edges, and built around people who actually show up and run together.

What I learned

A club website can quickly become a product.

Once people depend on it for schedules, events, membership, public identity, sponsorships, and communication, the work is no longer just about pages and styling.

It becomes a system with different types of users, different levels of access, sensitive data, operational workflows, and public-facing content that still needs to feel personal.

The most valuable part of this project was connecting those layers:

Public website → verified membership → personal profile → community directory → admin operations

React · TypeScript · Supabase · Cloudflare · Product Design