Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/asubap/website/llms.txt

Use this file to discover all available pages before exploring further.

Beta Alpha Psi Beta Tau Chapter’s resource ecosystem has two distinct surfaces: the Sponsors Network page (/sponsors-network) where authenticated members browse a directory of all sponsors, and the Resources page (/resources) where they access files uploaded by those sponsors. This document covers both views, the data shapes they consume, and how sponsor-uploaded files — stored in Vercel Blob — reach members through signed URLs generated by the backend.

Sponsors Network Page — /sponsors-network

SponsorsNetworkPage is a protected route that lets any authenticated member (including sponsors and e-board members) explore the full sponsor directory. It fetches a summary list from the backend, then provides fuzzy-search and sort controls on top.

Data Fetching

GET ${VITE_BACKEND_URL}/sponsors/summary
Authorization: Bearer <session.access_token>
The response is an array of BackendSponsor objects:
interface BackendSponsor {
  id?: number;
  company_name?: string;
  about?: string;
  links?: string | null;       // May be JSON string, CSV, or array
  pfp_url?: string;
  resources?: SponsorResource[]; // Not populated by /sponsors/summary
  tier?: string;
  emails?: string[];             // Not populated by /sponsors/summary
}
The page transforms each item into the canonical Sponsor type before passing it to NetworkList:
// Parsed result shape (Sponsor from types/index.ts):
{
  id: string;
  type: "sponsor";
  name: string;          // company_name || "Unknown Sponsor"
  tier?: string;         // e.g. "gold", "silver", "bronze"
  about: string;
  links: string[];       // Parsed from JSON/CSV/array
  photoUrl: string;      // pfp_url || "/placeholder-logo.png"
  resources: [];         // Not included in /summary
  emails: [];            // Not included in /summary
}
The links field from the backend may arrive as a JSON-encoded string, a comma-separated string, or a plain array. The transformation logic tries JSON.parse, then falls back to splitting on commas.
Fuzzy search is powered by Fuse.js with the following key weights:
FieldWeight
name0.8
about0.4
tier0.3
The search threshold is 0.3 — tight enough to avoid noise while still handling typos.
const fuseOptions = {
  includeScore: true,
  threshold: 0.3,
  keys: [
    { name: "name", weight: 0.8 },
    { name: "about", weight: 0.4 },
    { name: "tier", weight: 0.3 },
  ],
};

Sorting

A SortDropdown lets members order the sponsor list by:
OptionValue
Tier (Highest First)tier-desc
Tier (Lowest First)tier-asc
Name (A–Z)name-asc
Name (Z–A)name-desc
The default sort is tier-desc so the highest-tier sponsors appear at the top.

NetworkList Component

NetworkList is a shared grid component used across Members, Alumni, E-board, and Sponsors network pages. It accepts an array of MemberDetail | Sponsor entities and renders a card grid.
interface NetworkListProps {
  entities: (MemberDetail | Sponsor)[];
}
Each card conditionally renders fields based on entity.type:
Shows email, total hours, first link, major, about, graduation year, rank, and job-search status. Clicking opens NetworkProfileModal.
The grid layout responds across breakpoints:
1 column  →  sm: 2 columns  →  lg: 3 columns
When a member clicks a sponsor card, SponsorProfileModal opens (rendered inside NetworkList). It displays:
  • Full-size company logo
  • Tier badge
  • Complete about text
  • All links (clickable, open in new tab)
  • Resource list for that sponsor (if any resources were uploaded)

Resources Page — /resources

The Resources page (ResourcesPage) is a protected route that aggregates all sponsor-uploaded files into categorized sections. Members can preview any file inline.

API Endpoint

GET ${VITE_BACKEND_URL}/resources
Authorization: Bearer <session.access_token>
The backend returns a categorized structure where each category corresponds to a sponsor. Each resource has a signed_url — a time-limited URL generated by Vercel Blob that allows direct browser access without exposing raw storage credentials.
// Typical response shape
[
  {
    category: "Sponsor Name",
    resources: [
      {
        id: number;
        label: string;
        signed_url: string;  // Time-limited Vercel Blob URL
        mime_type: string;   // e.g. "application/pdf"
        uploadDate?: string;
      }
    ]
  }
]

Resource Preview

Clicking View on any resource opens ResourcePreviewModal, which accepts:
{
  name: string;       // The resource label
  signed_url: string; // The Vercel Blob signed URL
  mime_type?: string; // Used to choose the preview renderer
}
PDF files are rendered inline; images are displayed directly; other file types show a download link.

File Storage Architecture

1

Sponsor uploads

Sponsor calls POST /sponsors/:name/resources with either multipart/form-data (files ≤ 4.5 MB) or a blobUrl from a client-side Vercel Blob upload (files > 4.5 MB). The backend stores metadata (label, URL, MIME type, upload date) in the database.
2

Backend generates signed URLs

When GET /resources is called, the backend retrieves stored blob URLs from the database and generates short-lived signed URLs via the Vercel Blob SDK before returning them to the client.
3

Member views file

The browser uses the signed URL to fetch the file directly from Vercel Blob storage. No auth token is needed for the storage request itself — security is enforced by the URL’s time-limited signature.
4

Sponsor manages files

From SponsorHome, sponsors can delete any of their files. Vercel Blob files are deleted via DELETE /blob-upload/sponsor/:name; legacy-stored files use DELETE /sponsors/:name/resources.

Access Control Summary

RouteRequired Role
/sponsors-networkAny authenticated user (session && role)
/resourcesAny authenticated user (session && role)
/sponsorrole.type === 'sponsor' only
Members, pledges, alumni, and e-board members can all browse /sponsors-network and /resources. Only users with the sponsor role can access the upload/management interface at /sponsor.
Sponsors are classified into tiers stored in the database. While the tier values are backend-managed, the frontend renders them with a capitalized display label (e.g., "gold""Gold Sponsor"). Tier affects default sort order in the Sponsors Network page — higher tiers appear first under the default tier-desc sort. E-board admins can change a sponsor’s tier via:
POST /sponsors/change-sponsor-tier
Body: { sponsor_name: string; tier: string }

Build docs developers (and LLMs) love