alumni_lookup

Application Architecture

Updated: November 26, 2025
Purpose: Document the two-domain architecture, routing structure, and component organization for the alumni_lookup application.


Table of Contents

  1. Overview
  2. Two-Domain Architecture
  3. Routing Structure
  4. Controller Namespaces
  5. Shared vs Site-Specific Components
  6. Layout System
  7. Future Growth Plans

Overview

The alumni_lookup application serves two distinct audiences through a subdomain-based architecture:

Domain Audience Purpose Authentication
lookup.bualum.co Internal staff Alumni research, engagement tracking, data management Required (Devise)
champions.bualum.co External alumni Champion signup flow, future champion portal Currently public
┌─────────────────────────────────────────────────────────────────────┐
│                        alumni_lookup Application                     │
├─────────────────────────────────┬───────────────────────────────────┤
│      lookup.bualum.co           │      champions.bualum.co          │
│      (Internal)                 │      (External)                   │
├─────────────────────────────────┼───────────────────────────────────┤
│  • Alumni Search                │  • Champion Signup Flow           │
│  • Engagement Stats             │  • (Future) Champion Portal       │
│  • Champion Management          │  • (Future) City Leader Tools     │
│  • Data Import/Export           │                                   │
│  • Settings/Admin               │                                   │
├─────────────────────────────────┴───────────────────────────────────┤
│                         Shared Components                            │
│  • Models (Alumni, ChampionSignup, Degree, etc.)                    │
│  • Services (EngagementScoreCalculator, etc.)                       │
│  • Database (PostgreSQL)                                            │
└─────────────────────────────────────────────────────────────────────┘

Two-Domain Architecture

Internal Site: lookup.bualum.co

The internal site provides staff-facing tools for alumni relationship management:

Core Features:

Access Control:

External Site: champions.bualum.co

The external site provides public-facing features for alumni engagement:

Current Features:

Planned Features (Future Phases):

Access Control:


Routing Structure

Subdomain Routing

The application uses Rails subdomain constraints to route requests:

# config/routes.rb

# Champions subdomain - external site
constraints subdomain: 'champions' do
  scope module: 'champions' do
    resources :signups, controller: 'champion_signups', only: [:new, :create, :show]
    root to: "champion_signups#new"
  end
end

# Default (no subdomain constraint) - internal site
# All other routes handle lookup.bualum.co

Route Categories

Public Routes (No Authentication)

| Route | Controller | Purpose | |——-|————|———| | GET / (champions) | Champions::ChampionSignupsController#new | Signup wizard start | | POST /signups (champions) | Champions::ChampionSignupsController#create | Process signup steps | | GET /signups/:id (champions) | Champions::ChampionSignupsController#show | Signup confirmation |

Authenticated Routes (Devise Required)

| Route | Controller | Purpose | |——-|————|———| | GET /alumni_search | AlumniController#search | Main search interface | | GET /alumni/:id | AlumniController#show | Alumni profile view | | GET /engagement_stats | EngagementStatsController#index | Analytics dashboard | | GET /champion_signups | ChampionSignupsController#index | Manage signups | | GET /batch_search | BatchSearchController#new | Bulk lookup |

Admin-Only Routes

| Route | Controller | Guard | |——-|————|——-| | /settings/* | Settings::* | ensure_admin | | /users | UsersController | authorize_admin! | | /people | PeopleController | ensure_admin |

API Routes (Internal Use)

| Route | Controller | Purpose | |——-|————|———| | GET /api/affinities | Api::AffinitiesController | Affinity dropdown data | | GET /api/alumni | Api::AlumniController | Alumni typeahead search | | GET /api/majors | Api::MajorsController | Major dropdown data | | GET /api/activity_descriptions | Api::ActivityDescriptionsController | Activity filter data |

See API.md for detailed API documentation.


Controller Namespaces

Namespace Structure

app/controllers/
├── application_controller.rb          # Base controller, auth helpers
├── public_controller.rb               # Base for public (unauthenticated) controllers
├── alumni_controller.rb               # Alumni search, show, update
├── alumni_affinities_controller.rb    # Alumni-affinity management
├── batch_search_controller.rb         # Bulk name/email lookup
├── champion_signups_controller.rb     # Internal champion management
├── engagement_activities_controller.rb # Activity listing
├── engagement_stats_controller.rb     # Analytics dashboard
├── people_controller.rb               # Alumni data import
├── statistics_controller.rb           # Degree statistics
├── users_controller.rb                # User management
│
├── api/                               # Internal JSON API
│   ├── activity_descriptions_controller.rb
│   ├── affinities_controller.rb
│   ├── alumni_controller.rb
│   └── majors_controller.rb
│
├── champions/                         # External site (subdomain)
│   └── champion_signups_controller.rb # Inherits from PublicController
│
└── settings/                          # Admin configuration
    ├── settings_controller.rb
    ├── affinities_controller.rb
    ├── alumni_controller.rb
    ├── colleges_controller.rb
    ├── engagement_activities_controller.rb
    └── majors_controller.rb

Namespace Responsibilities

Namespace Base Class Purpose
(root) ApplicationController Core internal features
Api:: ApplicationController JSON endpoints for JavaScript
Champions:: PublicController External public-facing features
Settings:: ApplicationController Admin-only configuration

Shared vs Site-Specific Components

Shared Components (Used by Both Sites)

Models

All models are shared between internal and external sites:

Model Internal Use External Use
Alumni Search, display, management Signup matching
ChampionSignup Review, merge, manage Create, update
Degree Display, import (read-only context)
EngagementActivity Stats, scoring (none currently)
Affinity Assignment, filtering (none currently)

Full association details: See MODEL_RELATIONSHIPS.md

Services

| Service | Purpose | Used By | |———|———|———| | EngagementScoreCalculator | Calculate engagement scores | Internal stats | | TopEngagedAlumniService | Generate leaderboards | Internal stats | | ChampionSignupMerger | Merge duplicate signups | Internal management | | AlumniMatcher | Match names to alumni records | Both sites | | AlumniFilterService | Filter alumni by various criteria | Internal stats | | EngagementStats::BaseService | Base class for stats services | Stats services | | EngagementStats::OverviewService | Overview tab calculations | Engagement stats | | EngagementStats::AnalyticsService | Analytics tab calculations | Engagement stats | | EngagementStats::BreakdownService | Breakdown tab calculations | Engagement stats | | EngagementStats::DemographicsService | Demographics tab calculations | Engagement stats | | EngagementStats::MatrixService | Matrix quadrant calculations | Engagement stats | | EngagementStats::ActivityPairsService | Activity pairs calculations | Engagement stats |

Helpers

| Helper | Scope | |——–|——-| | ApplicationHelper | Global utilities | | ChampionSignupsHelper | Signup flow questions/logic | | EngagementStatsHelper | Stats formatting | | AffinitiesHelper | Affinity name lookups |

Site-Specific Components

Internal Site Only

External Site Only


Layout System

Available Layouts

Layout File Used By
application app/views/layouts/application.html.erb All internal pages
public app/views/layouts/public.html.erb Champions subdomain
devise (inherited) Login/password pages

Layout Selection

# Internal controllers use application layout by default

# Champions controllers explicitly use public layout
class Champions::ChampionSignupsController < ApplicationController
  layout "public"
end

Future Growth Plans

Phase 1: Champion Authentication (Planned)

Phase 2: City Leadership Council

Phase 3: Enhanced Champion Portal

Architectural Considerations for Growth

  1. Authentication Strategy
    • Consider separate Devise scope for champions vs staff
    • Or: unified User model with role-based access
    • See AUTHENTICATION.md for detailed planning
  2. Controller Organization
    • May need Champions::Dashboard controller
    • May need Champions::Profile controller
    • Consider Champions::BaseController for shared logic
  3. Database Considerations
    • Champion user data vs Alumni record linking
    • Session management for external users
    • Audit logging for sensitive operations

Namespace Boundary Rules

This section defines the rules for placing controllers and features in the correct namespace, ensuring clean separation between internal and external functionality.

Controller Inheritance Rules

Controller Type Base Class Layout Auth Required
Internal features ApplicationController application Yes
Settings/Admin ApplicationController + ensure_admin application Yes + Admin
Public features PublicController public No
Champion portal (future) PublicController + auth public Yes (Champion role)

Namespace Placement Rules

app/controllers/ (Root)

For: Core internal features used by staff

Includes:

Do NOT place here:

app/controllers/api/

For: JSON API endpoints for JavaScript components

Includes:

Rules:

app/controllers/champions/

For: External site features (champions.bualum.co)

Currently Includes:

Future additions should include:

Rules:

app/controllers/settings/

For: Admin-only configuration and data management

Currently Includes:

Rules:

Future Controller Placement

When implementing role-based access, follow these placement rules:

Internal Site (lookup.bualum.co) - Admin and Staff roles:

Feature Namespace Base Class Notes
Staff Features Root ApplicationController Internal site
Admin-only Settings Settings:: ApplicationController Internal site
Admin User Management Root (UsersController) ApplicationController Internal site

External Site (champions.bualum.co) - CLC and Champion roles:

Feature Namespace Base Class Notes
Champion Dashboard Champions:: PublicController + champion auth External site
Champion Profile CRUD Champions:: PublicController + champion auth External site
CLC Regional Dashboard Champions::Regional PublicController + CLC auth External site
CLC Champion Management Champions::Regional PublicController + CLC auth External site

Note: CLC (City Leadership Council) is an external/Champion Portal role, not an internal role. CLC is to Champion as Admin is to Staff—the “regional admin” version.

Service Object Usage for Role-Based Features

The EngagementStats::* service objects were created to support future role-based features:

# Example: CLC regional dashboard using champion-facing services with regional filtering
class Champions::RegionalDashboardController < PublicController
  before_action :require_city_leader!

  def index
    # Future: Pass regional filter to services
    @regional_champions = ChampionSignup.where(region: current_champion.region)
    @regional_stats = Champions::RegionalStatsService.new(region: current_champion.region).calculate
  end
end

Service Design Principles:

  1. Services should accept filter parameters (region, college, time period)
  2. Controllers should NOT contain business logic—delegate to services
  3. Services can be shared between different role levels with different filters
  4. Keep services stateless and testable


Last updated: November 2025