UCI Phi Kappa Psi Website

Full-stack fraternity chapter website built with Angular, Firebase, and Hygraph CMS

AngularTypeScriptFirebaseGraphQLApolloHygraph CMSRxJSAngular Material
www.uciphipsi.kevinnorgaard.com
UCI Phi Kappa Psi Website screenshot

01Problem Statement

The Phi Kappa Psi chapter at UCI had no centralized digital presence — recruitment, alumni outreach, event coordination, and leadership history were all managed manually or scattered across disconnected tools. Officers needed a platform that could serve three distinct audiences (recruits, active members, alumni) and stay relevant year-round without requiring a developer for every content update or seasonal change.

02Architecture

Hygraph serves exec profiles, leadership history, and composite galleries via Apollo GraphQL — zero redeployment for content updates. The root route swaps at build time via an environment flag (normal / rush / philanthropy) to serve different seasonal landing pages from the same codebase. The admin dashboard is gated behind Firebase Auth and reads/writes rushee forms, event check-ins, and alumni records to Firebase Realtime Database.

03Data Model

Firebase Realtime Database

forms:
  "{phone}":
    name:         "LastName, FirstName"
    email:        string
    year:         string
    major:        string
    minor:        string
    cumGpa:       string
    prevGpa:      string
    sports:       string
    achievements: string
    reasons:      string
    referral:     string
    notes:        string  # admin-added
    socialMedia:
      facebook:   string
      instagram:  string
      linkedin:   string

checkins:
  "{phone}":
    "{date}": true  # date format: "YYYY-M-D"

alumni:
  "{name}":
    fullName: string
    email:    string

Hygraph CMS

type Image {
  fileName: String!
  url:      String!
}

type Executive {
  name:     String!
  position: String!
  image:    Image
  url:      String
  order:    Int!
}

type Leader {
  name:  String!
  title: String!
  year:  Int!
}

type MembershipPage {
  compositeImage: Image!
  compositeYear:  Int!
}