This site is driven by two keys, like the machine it came from. Reading: j and k scroll, d and u move half a page, gg goes to the top, G to the bottom, H and L switch windows, ? opens the help. Space is the Neovim leader and handles content: Space then h home, r research, p projects, g gear, a about, / tags, or Space then a digit to jump to that window. Home is the tmux prefix and handles windows: Home then c opens a terminal, Home then & closes a window, Home then space goes to the next one. While focus is on the keyboard, h j k l move between keys and Enter opens one.

ResearchR AboutA Gear — G for gear — keyboard, terminal, editor, homelab.G
    ProjectsP Tags — / as in vim: search./
    ×
    Menu

    beepresent: A CLI and API for the Campus Course Portal

    A course-portal scraper wrapped as an API and a CLI — course lists, assignments, quizzes, and attendance submission, with a one-week cache because the data barely moves.

    Overview

    This project is a CLI and API for interacting with course data — listing courses, fetching details, retrieving assignments and quizzes, and submitting attendance records (“present”).

    API

    EndpointDescription
    GET /coursesList all courses
    GET /courses/{id}Fetch course details
    GET /courses/{course_id}/assignmentsList assignments for a course
    GET /courses/{course_id}/quizzesList quizzes for a course
    POST /courses/{course_id}/present/{present_id}Submit attendance

    CLI

    The CLI mirrors the API surface:

    • bl courses — list courses
    • bl courses {id} — show course details
    • bl present — submit attendance

    Scheduling

    Attendance submissions should run on a fixed schedule:

    • Monday – Friday: 7:00 PM – 8:00 PM
    • Saturday: 9:00 AM, 11:00 AM, 2:00 PM, 4:00 PM

    Open question: should the scheduler live inside this project, or be a separate concern?

    Caching & Invalidation

    Course data rarely changes, so aggressive caching isn’t a problem.

    • Cache entries expire after one week
    • Re-crawling only happens when cached data has expired
    • Invalidation on every access is avoided — it’s not a priority

    Implementation

    Tech Stack

    • TypeScript
    • Bun.js runtime
    • Cheerio for HTML parsing

    Project Structure

    src/
    ├── services/
    │   ├── getCourses
    │   ├── getCourseDetail
    │   ├── getPresentationList
    │   └── postPresent
    ├── repository/
    │   ├── courses
    │   ├── assignments
    │   └── quiz
    ├── utils/
    │   └── log
    └── config/
        └── creds
    id en
    rss gh in