Nanobots Producing Megastructures
    Have ideas to improve npm?Join in the discussion! »

    TypeScript icon, indicating that this package has built-in type declarations

    0.0.8 • Public • Published

    CourseLore · The Open-Source Student Forum

    Source Package Continuous Integration

    Run the CourseLore Demonstration Server on Your Own Computer

    You may run the CourseLore demonstration server on your own computer to play around, try out the features, and determine if CourseLore works for you.

    (Note: We say that it’s a demonstration server because you shouldn’t run CourseLore this way for an actual course (your students wouldn’t be able to access it) (see § Host Your Own CourseLore Instance when you’re ready to take that next step). We do not mean demonstration as in “now go buy CourseLore Premium,” or “here are some in-app purchases.” There are no CourseLore Premium or in-app purchases. CourseLore is and will always be free and open-source.)

    • Option 1 (Simplest): Download CourseLore, run it, and go to http://localhost:4000. (To run CourseLore in macOS you’ll need to right-click on the executable, click on Open, and then confirm that you want to open it. CourseLore as downloaded from the the link above is safe, but hasn’t been signed, so macOS makes you confirm that you trust it.)

    • Option 2 (Advanced): If you have Node.js installed, run:

      $ npx courselore
    • Option 3 (More Advanced): Run:

      $ git clone
      $ cd courselore
      $ npm install
      $ npm start

    Host Your Own CourseLore Instance

    Follow the instructions below to install CourseLore on your own servers. This is the most privacy-preserving way of using CourseLore, because your and your students’ data are under your control. It’s a bit of extra work to setup, but CourseLore has been designed from the beginning to be easy to install and maintain, so it’s an excellent first system administration project. And once it’s been setup, you can mostly forget about it.


    • Domain: A domain is an address where you’ll find your CourseLore installation, for example,

      You may use a subdomain under your institution’s domain (for example, courselore.<university>.edu) or a domain that you buy (for example, For this second option, most domain sellers work (for we use Namecheap) (when looking at domain sellers you may also see them being called registrars).

      The important thing to keep in mind when you’re getting a domain is that you must be able to configure a few DNS records for it (more on that below). If you’re using a subdomain under your institution’s domain, ask the system administrator if they can configure a few DNS records for you. If you’re buying your own domain, check with the domain seller if they provide some sort of DNS service that you can configure (most of them do).

    • Server: A server is just a regular computer that’s always on and connected to the internet.

      You may use a server that’s provided by your institution or a server that you rent. For this second option, most providers of servers for rent work (for we use DigitalOcean, and another popular option is linode) (when looking at servers for rent you may also see them being called Virtual Private Servers (VPSs)).

      In theory you could run CourseLore on a computer that you have at home or at your office, as long as it’s always on and connected to the internet. CourseLore doesn’t use a lot of resources so even an old computer or something like a Raspberry Pi would be enough. But in practice that probably won’t work because CourseLore needs to run a web server, send emails, and so forth, and most domestic internet service providers disable that kind of activity to prevent spam and other kinds of abuse.

      The important things to keep in mind when you’re getting a server are that you must be able to:

      1. Run network services, for example, a web server and an email server. In particular, you must be able to bind services to the network ports 80 and 443 for inbound connections, and you must be able to make outbound connections to port 25. You may also check for firewalls sitting in front of the server.
      2. Have access to the file system (read and write files). (Most providers of Platform-as-a-Service (PaaS), for example, Heroku, fail this criterion.)

      If you plan on using a server provided by your institution, you may ask your system administrator about these features. Most servers for rent provide these features.

    Setup a Development Environment to Contribute to CourseLore

    CourseLore has been designed to be a welcoming project for people who are new to contributing to open-source. Here’s what you need to install to get started:

    Clone and setup the project locally:

    $ git clone
    $ cd courselore
    $ npm install
    $ code .

    Run the development server:

    $ npm start

    Run the tests:

    $ npm test

    Release a new version:

    $ npm version <major|minor|patch>
    $ git push --tags

    Insiders Builds

    Insiders Builds are generated on every push. They’re useful for development and testing, and are not recommended for regular users. Insiders Builds are available as GitHub Action Artifacts (you must be logged into GitHub to download an Artifact).




    • Basic CRUD:
      • Rename course, and that sort of thing
    • Enrollment (user course) roles
      • Instructor
      • Assistant
      • Student
    • States
      • Draft
      • Enrollment
      • Running
      • Archived
    • Create roles and manage permissions
    • Tag-based actions
    • Allow course assistants to create courses?
    • Different ways to enroll in the course
      • Invitation only
      • By URL
      • What roles can sign up for themselves
      • Course manager (instructors?) should confirm sign up
      • Generate a QR code with link, for instructors to use in class
    • Manage people in the course
      • Change their roles
      • Remove them from the course
    • Allow people to disenroll from a course (but we get to keep their contributions as “ghost”)
    • Allow people who aren’t even users to sign up & enroll in a single operation
      • Do it with a simple redirect option in the sign up process
    • Enroll with link or with a list of emails.
      • Different links for different roles.
      • Expiration dates on links.


    • Only one kind of post in threads
    • Configurable anonymity
      • Only instructors may identify the person
      • Instructors and assistants may identify the person (default)
      • No-one may identify the person
    • Don’t implement that idea of collaboratively coming up with an answer (like Piazza) (no-one in the courses I was involved with used that; people just write follow-up answers)
    • Notifications
      • How
        • Email
        • In-app
      • What
        • Subscribe to threads
        • Subscribe to whole courses
        • Staff may send messages that are notified to everyone
    • Tags
    • Reactions & Badges
      • Only allow positive reactions? (Like Facebook) (Probably yes)
      • Allow both positive and negative reactions? (like GitHub / Reddit)
      • Created by/Endorsed by instructor
    • States
      • Open
      • Closed
    • Visibility
      • To students
      • To staff only (and students that may have posted on it)


    • To integrate with other platforms, like, LMS
    • To ask a question from within the text editor, for example



    User Profile

    • Usual CRUD on user profile (name, and so forth).
    • Gravatar.
    • Multiple emails? Probably not, just the one institutional email (which is the account identifier). If people are affiliated with many institutions it’s likely they’ll be using different CourseLore instances anyway…
    • Allow people to remove their accounts.


    • People may want to integrate CourseLore with their existing LMS & other systems.

    Text Processor

    Landing Page

    • Try to make animation consume less resources. (Currently it’s making the “this tab is consuming too much energy” warning pop up in Safari.)
      • Maybe it has to do with computing the sine of large numbers? Clamp the values between 0–2π to see if that helps…

    Textarea Niceties

    • GitHub-style, not Trix-style.
    • Store what the user wrote per thread/chat, even if they move to other threads/chats.
      • Garlic.js does that, but it seems a bit old and requires jQuery. Use localStorage instead.
    • Some helpers to input Markdown & LaTeX (similar to what GitHub has).
    • Upload files (like images), and have them embedded (similar to what GitHub has).
      • Packages to handle multipart form data: busboy, multer, formidable, multiparty, connect-multiparty, and pez.
    • Templates for questions (like GitHub Issues).


    Error Pages

    • 400s.
    • 500s.
    • Form validation errors.


    • In contents of a course (for example, search for NullPointerException to find that thread that helped you out).
      • Search within the scope of a course.
      • Search in all courses you’re taking (for example, search for deadline extension).
      • Reference: GitHub let’s you search in different scopes like that.
    • Courses in the system (for joining a course).

    Translate to Other Languages


    • For courses in which participation is graded.

    Live Course Communication during the Lectures

    Non-Functional Features

    • Easy to self-host
    • Works on mobile (no apps) & desktop
    • Modern & uncluttered interface
    • Fast



    Page Transitions & Client-Side JavaScript

    Code Base



    Open-Source Contributions


    • Newsletter
    • Create CourseLore Gravatar
      • Use in npm
    • Create accounts on:
      • Patreon
      • PayPal
      • Facebook
      • Instagram
      • Reddit



    • Developed a two-column layout for the course pages and fleshed out the styles across the application.
    • Developed @leafac/css.
    • Released caxa@1.0.0.
    • Released a video about the background animation on the homepage.
    • For next week:
    • Threads are working.
    • Worked on styles & the small details:
      • Text editor.
      • Relative time (for example, 3 hours ago).
      • Logo animation.
      • Buttons go into a ‘loading’ state to prevent double-submission.
      • Links change color.
    • Started an utility to process CSS.
    • Multiplatform testing & development setup.
    • What should I work on next?
      • Options:
        • More forum-related features:
          • Notifications on updates
          • Anonymity.
          • Tags.
          • Instructor endorsed answers.
        • More onboarding features:
          • Invitations.
      • Answers:
        • For next week:
          • Threads list on a column on the left.
          • Tab on the text editor.
          • Make entries more lightweight.
          • Why isn’t the home two column?
          • Onboarding is broken.
        • Long-term:
          • Anonymity.
          • Search.
          • Filtering.
            • Only show my posts.
          • Nested posts.
          • Chat.
            • Integrated with the forum, not as two modalities.
            • A chat could be just another thread.
          • Groups.
          • Pin conversations.
    • Demonstration:
      • Clearer communication in sign-up/sign-in.
      • Create course.
      • Join course.
      • Create thread.
    • Automated tests.
      • Got + JSDOM / Puppeteer / Cypress / Selenium.
    • The packaging is working on Windows.
    • What do we want the text editor to look like?
      • Simple, like GitHub’s.
    • How to invite people to the course?
      • With link.
        • Different links for different roles.
      • With a list of emails.
      • Expiration dates on invitations.
    • How should threads look like? One page for the list of threads and one page per thread (à la GitHub Issues), or one page with both the list of threads and one thread (à la (and Piazza, for that matter…))?
      • We’re going GitHub-style on mobile and style on the desktop.
    • Show participation grades for courses in which that’s graded. (We don’t do the grading, we just present the statistics.)
    • Templates for questions.
    • Live course communication during the lectures:
    • Finish the account creation workflow and wired it to the authentication workflow demonstrated last week.
    • Tried to use ECMAScript modules (because of top-level async/await). Still too fresh. While Node’s support for them isn’t experimental anymore, some of the underlying infrastructure still is, so other tools in the ecosystem (for example, Jest & ts-node-dev) don’t support them very well (require flags and whatnot).
    • Had issues with some native modules (for example, sharp) not working with @leafac/pkg. Ended up creating
    • Had issues with types for Ended up creating
    • Created a proper demonstration mode for CourseLore.

    Progress Report

    • The text processor for posts is done. It supports Markdown, LaTeX, and syntax highlighting. Also, it’s secure against Cross-Side Scripting (XSS) attacks. Here’s some input that exercises all these features.

    • Setup the infrastructure for GitHub Actions:

      • Run the test suite on Linux, macOS, and Windows.
      • Create binaries for all these operating systems.
      • Distribute the binaries as releases and as nightly builds (GitHub Actions Artifacts)
    • Released the following packages:

      • If people already have Node.js installed, they may try CourseLore with npx courselore. Also, they may npm install courselore to mount CourseLore as part of a bigger Node.js application. That isn’t the preferred deployment strategy (using the binaries is), but it’s a possibility for advanced users.

      • Rehype is part of the text processor, and Shiki is a syntax highlighter based on Visual Studio Code’s syntax highlighter. is a package that connects the two and improves on the existing with support for the latest Shiki version, some architectural differences that decouples the dependencies a little better, and brings TypeScript support.

      • A safe and convenient way to use JavaScript’s tagged template literals as an HTML template engine.

      • Fixes some problems with, particularly in how it manages native modules.

    Design Decisions

    • The course URLs may be:

      • In a flat namespace or in a hierarchical namespace. A flat namespace is like Reddit’s /r/<name>, and a hierarchical namespace is like GitHub’s /<user-or-organization>/<repository>.

        • A flat namespace is good because it’s simpler, particularly in self-hosted installations for a single user (think of how silly<course> looks).

        • A flat namespace is bad because it clashes easily (think of multiple teaching a course identified as cs-101).

        • A hierarchical namespace makes sense when there’s the notion of organizations, which could be a group of people who have several courses together. That case probably is rare.

      • Given by the user, or generated by the system. An URL given by the user is like Reddit’s and GitHub’s URLs (for example<repository>). An URL generated by the system is like YouTube (for example,<random-string-that-is-the-video-identifier>).

        • An URL given by the user is simpler to share (think of an URL projected on the board in a classroom).

        • URLs given by the user are more complex for the system, because we have to handle renames, redirects, and so forth.

      • We decided to go with a flat namespace and system-generated URLs. For example, Because URLs are generated by the system, we don’t see a need for a subpath like /r/<something>. We know not to generate identifiers that would clash with routes we’d want to use, for example /settings. We may want to have some sort of aliasing in the future so users can create their own readable URLs if they want.

      • References:

        • Piazza has alises like
        • Campuswire uses the Reddit approach with URLs like
        • They have different URLs for joining a course and then later for visiting it. We don’t want that.
        • only has the magic link approach.
        • A technology to handle authentication.
    • Authentication methods:

      • The options are:

        1. A plain username/password authentication strategy.
        2. A magic link approach like Slack.
        3. Single sign-on integrated with universities’ systems.
      • We’re going with Option 2 for now, as it seems like a good sweet-spot in terms of security, simplicity to implement, and generality. It works for every university without extra effort on our part. That said, we may still give Option 1 as an alternative (as Slack does). Also, people may customize CourseLore with their own routes to implement Option 3.

      • Note: We’re following Slack in the approach to authentication (the so-called magic link), but we’re not going to have the weird separation of accounts per team that Slack has. There will only be one CourseLore account per email and the user may join multiple courses.



    npm i courselore

    DownloadsWeekly Downloads






    Unpacked Size

    6.89 MB

    Total Files


    Last publish


    • avatar