by team Inference
Course-Compass is an interactive web application for exploring KTH courses. It allows users to search, filter, and review courses while providing prerequisite visualization and personalized recommendations. The application uses Firebase for data storage and real-time updates.
- Course search with advanced filtering
- Course reviews and ratings
- Interactive prerequisite visualization
- Transcript upload for eligibility checking
- Personal course favorites
- Dark/Light mode support
Running this project locally can be done via docker or by building and running it with npm.
Executing
docker compose upor
docker-compose upbuilds and starts the container.
After downloading the repository navigate to the folder my-app and install the dependencies with
npm ciThe website can run for developers with
npm run devfor production use
npm run buildThis project uses Firebase for backend services. To set up your development environment:
Update the api keys in firebase.js to your keys.
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL:"",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
};To populate the Firebase database with course data:
- Use the JSON file in
/src/assets/example.jsonor prepare a file according to the following outline:
{
"courseCode": {
"code": "string",
"name": "string",
"location": "string",
"department": "string",
"language": "string",
"description": "string",
"academic_level": "string",
"periods": "array",
"credits": "number",
"prerequisites": "object",
"prerequisites_text": "string",
"learning_outcomes": "string"
}
}- Use the
model.populateDatabase(data)function to upload courses:
import data from "./assets/example.json";
model.populateDatabase(data);Click to view Firebase Rules
{
"rules": {
// Courses and Metadata
"courses": {
".read": true,
".write": "auth != null && (auth.uid === '6qKa992eL4fRkGKzp3OG5Sjjk983' || auth.uid === 'wa9HoCfWe2Vpw6J7oiq5oCxNYz52')"
},
"metadata": {
".read": true,
".write": "auth != null && (auth.uid === '6qKa992eL4fRkGKzp3OG5Sjjk983' || auth.uid === 'wa9HoCfWe2Vpw6J7oiq5oCxNYz52')"
},
"departments": {
".read": true,
".write": "auth != null && (auth.uid === '6qKa992eL4fRkGKzp3OG5Sjjk983' || auth.uid === 'wa9HoCfWe2Vpw6J7oiq5oCxNYz52')"
},
"locations": {
".read": true,
".write": "auth != null && (auth.uid === '6qKa992eL4fRkGKzp3OG5Sjjk983' || auth.uid === 'wa9HoCfWe2Vpw6J7oiq5oCxNYz52')"
},
// Reviews and Comments
"reviews": {
".read": true,
"$courseCode": {
"$reviewUserID": {
// Only the original author can write the main review
".write": "auth != null && (auth.uid === $reviewUserID || data.child('uid').val() === auth.uid || !data.exists())",
".validate": "newData.hasChildren(['text', 'timestamp']) &&
newData.child('text').isString() &&
newData.child('text').val().length <= 2501 &&
newData.child('timestamp').isNumber()",
// Allow any signed-in user to write comments under the review
"comments": {
".write": "auth != null",
"$commentId": {
".validate": "newData.hasChildren(['text', 'userName', 'timestamp']) &&
newData.child('text').isString() &&
newData.child('userName').isString() &&
newData.child('timestamp').isNumber()"
}
}
}
}
},
// User-specific Data
"users": {
"$userID": {
".read": "auth != null && auth.uid === $userID",
".write": "auth != null && auth.uid === $userID"
}
}
}
}
To deploy these rules:
firebase deploy --only database- Never commit
.env.localto version control - Keep your Firebase credentials secure
- Contact the team lead if you need access to the Firebase configuration
The project uses the Model–view–presenter (MVP) paradigm. The view displays the data. The presenter contains the logic. The model contains the data.
- /src/model.js: Core data model and business logic
- /src/views/: UI components and layouts
- /src/presenters/: Interface between Model and View
- /src/scripts/: Utility scripts including transcript parsing
- /src/assets/: Static resources and images
- /src/dev/: Development utilities and component previews
- /src/presenters/Tests/: Test implementations
- /scripts/transcript-scraper/: Transcript parsing tools
Click to view Project Tree
.
├── docker-compose.yml
├── Dockerfile
├── docs
│ ├── _config.yml
│ └── index.md
├── my-app
│ ├── dist
│ │ ├── assets
│ │ │ ├── index-BNDm07oX.js
│ │ │ ├── index-Bwi9_b9d.css
│ │ │ ├── pdf.worker-CKnUz2wA.mjs
│ │ │ └── project_icon-CgaTQWFX.png
│ │ └── index.html
│ ├── eslint.config.js
│ ├── firebase.js
│ ├── firebase.json
│ ├── firebaseModel.js
│ ├── index.html
│ ├── package.json
│ ├── package-lock.json
│ ├── postcss.config.js
│ ├── public
│ │ ├── favicons-dark
│ │ │ ├── android-chrome-192x192.png
│ │ │ ├── android-chrome-512x512.png
│ │ │ ├── apple-touch-icon.png
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── favicon.ico
│ │ │ └── site.webmanifest
│ │ └── favicons-light
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon-32x32.png
│ │ ├── favicon.ico
│ │ └── site.webmanifest
│ ├── src
│ │ ├── assets
│ │ │ ├── example.json
│ │ │ ├── project_icon1.png
│ │ │ ├── project_icon.png
│ │ │ └── share_icon.png
│ │ ├── dev
│ │ │ ├── index.js
│ │ │ ├── palette.jsx
│ │ │ ├── previews.jsx
│ │ │ ├── README.md
│ │ │ └── useInitial.js
│ │ ├── index.jsx
│ │ ├── model.js
│ │ ├── pages
│ │ │ ├── App.jsx
│ │ │ └── SharedView.jsx
│ │ ├── presenters
│ │ │ ├── AddToDB.jsx
│ │ │ ├── FilterPresenter.jsx
│ │ │ ├── ListViewPresenter.jsx
│ │ │ ├── PrerequisitePresenter.jsx
│ │ │ ├── ReviewPresenter.jsx
│ │ │ ├── SearchbarPresenter.jsx
│ │ │ ├── SidebarPresenter.jsx
│ │ │ ├── Tests
│ │ │ │ ├── AddToDB.jsx
│ │ │ │ ├── AllCoursesPresenter.jsx
│ │ │ │ └── JsonToDatabase.jsx
│ │ │ └── UploadTranscriptPresenter.jsx
│ │ ├── scripts
│ │ │ ├── eligibility_refined.js
│ │ │ └── transcript-scraper
│ │ │ ├── transcript-gpt.html
│ │ │ ├── transcript-scraper-htmlTester.html
│ │ │ └── transcript-scraper.mjs
│ │ ├── styles.css
│ │ └── views
│ │ ├── Components
│ │ │ ├── CoursePagePopup.jsx
│ │ │ ├── CourseViewComponents
│ │ │ │ ├── ModalComponent.jsx
│ │ │ │ └── SampleComponent.jsx
│ │ │ ├── FavouriteDropdown.jsx
│ │ │ ├── PrerequisiteTreeComponents
│ │ │ │ └── BoxTest.jsx
│ │ │ ├── RatingComponent.jsx
│ │ │ ├── SideBarComponents
│ │ │ │ ├── ButtonGroupField.jsx
│ │ │ │ ├── ButtonGroupFullComponent.jsx
│ │ │ │ ├── CollapsibleCheckboxes.jsx
│ │ │ │ ├── CourseTranscriptList.jsx
│ │ │ │ ├── DropDownField.jsx
│ │ │ │ ├── FilterEnableCheckbox.jsx
│ │ │ │ ├── SliderField.jsx
│ │ │ │ ├── ToggleField.jsx
│ │ │ │ ├── ToolTip.jsx
│ │ │ │ └── UploadField.jsx
│ │ │ └── StarComponent.jsx
│ │ ├── ListView.jsx
│ │ ├── PrerequisiteTreeView.jsx
│ │ ├── ReviewView.jsx
│ │ ├── SearchbarView.jsx
│ │ ├── SidebarView.jsx
│ │ ├── TestAllCoursesView.jsx
│ │ └── TestWithButtonView.jsx
│ ├── tailwind.config.js
│ └── vite.config.js
└── README.md
21 directories, 87 files
The docs branch contains the team website.
The kth-api contains most of the tools used for gathering and processing the course info.