Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cornell-dti/course-plan/llms.txt

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

Courseplan is a single-page application built with Vue 3 and TypeScript, bundled by Vite, with global state managed by Vuex 4 and persistence handled by Firebase/Firestore. Understanding how these layers connect makes it straightforward to find where any given piece of behaviour lives.

Tech stack

LayerTechnology
UI frameworkVue 3 (Composition API + Options API)
Type systemTypeScript ≤ 4.1.5
Global stateVuex 4 (src/store.ts)
Build toolVite 2
Backend / authFirebase 9 (Firestore + Google Auth)
StylingSCSS + Bootstrap 4
TestingJest (unit) + Cypress (e2e)

Key directories

src/
├── components/          # Reusable Vue components (modals, course cards, semester rows, …)
├── containers/          # Page-level container components (App.vue, onboarding, …)
├── requirements/        # Requirement computation engine
│   ├── types.ts         # Shared TypeScript types (CollegeOrMajorRequirement, RequirementChecker, …)
│   ├── requirement-graph.ts              # RequirementFulfillmentGraph data structure
│   ├── requirement-graph-builder.ts      # Builds the graph from decorated requirements + user courses
│   ├── requirement-frontend-computation.ts  # Produces GroupedRequirementFulfillmentReport for the UI
│   └── requirement-json-generator.ts     # CLI script: compiles TS requirement files → JSON
├── data/
│   ├── majors/          # Per-major requirement definitions (cs.ts, ece.ts, …)
│   ├── colleges/        # Per-college requirement definitions (en.ts, as.ts, …)
│   └── index.ts         # Aggregates all requirement data
├── store.ts             # Vuex store — single source of truth for all runtime state
├── firebase-config.ts   # Firebase project initialisation
├── feature-flags.ts     # GateKeeper feature flag system
└── schedule-generator/  # Experimental schedule-generation logic

Data flow

Firestore is the persistent source of truth. On login, the store subscribes to the user’s Firestore document via onSnapshot. Every mutation in the store that changes user data writes back to Firestore via setDoc / updateDoc.
Firestore (cloud)
      │  onSnapshot (realtime listener)

store.ts  ─── Vuex mutations / actions ───►  Firestore (writes)

      │  reactive state

Vue components  ──  computed properties  ──►  rendered UI

Vuex store state shape

VuexStoreState in src/store.ts defines every field held in memory at runtime:
export type VuexStoreState = {
  // Auth
  currentFirebaseUser: SimplifiedFirebaseUser;
  userName: FirestoreUserName;

  // Onboarding / profile
  onboardingData: AppOnboardingData;       // college, major, minor, grad year, exam credits, …
  orderByNewest: boolean;

  // Course data (derived from semester semesters for perf)
  derivedCoursesData: DerivedCoursesData;  // courseMap, courseToSemesterMap, duplicates

  // Requirement fulfillment
  toggleableRequirementChoices: AppToggleableRequirementChoices;
  overriddenFulfillmentChoices: FirestoreOverriddenFulfillmentChoices;
  userRequirementsMap: Readonly<Record<string, RequirementWithIDSourceType>>;
  dangerousRequirementFulfillmentGraph: RequirementFulfillmentGraph<string, CourseTaken>;
  safeRequirementFulfillmentGraph: RequirementFulfillmentGraph<string, CourseTaken>;
  courseToRequirementsInConstraintViolations: ReadonlyMap<string | number, Set<string[]>>;
  doubleCountedCourseUniqueIDSet: ReadonlySet<string | number>;
  groupedRequirementFulfillmentReport: readonly GroupedRequirementFulfillmentReport[];

  // UI / display
  subjectColors: Readonly<Record<string, string>>;
  uniqueIncrementer: number;
  uniqueBlankCourseIncrementer: number;
  isTeleportModalOpen: boolean;

  // Plans and saved courses
  plans: readonly Plan[];
  currentPlan: Plan;
  savedCourses: readonly Collection[];
  allSavedCourses: Collection;
};

Requirements computation pipeline

Requirement fulfillment is computed in several sequential stages each time the user’s courses or profile changes:
src/data/*  (TypeScript source)

      │  npm run req-gen

src/assets/requirements/decorated-requirements.json   (pre-computed eligible course IDs)

      │  requirement-graph-builder.ts

RequirementFulfillmentGraph<string, CourseTaken>      (bipartite: requirements ↔ courses)

      │  requirement-frontend-computation.ts

GroupedRequirementFulfillmentReport[]                 (one report per college / major / minor)

      │  Vuex store → reactive props

Requirements sidebar + course row indicators          (UI)
The graph is computed twice per state change — a dangerousRequirementFulfillmentGraph that allows double-counting and a safeRequirementFulfillmentGraph that does not — so the UI can highlight conflicts.
decorated-requirements.json is a build artifact checked into the repository. It must be regenerated via npm run req-gen whenever requirement TypeScript files change. See Adding and updating requirements for details.

Build docs developers (and LLMs) love