{"id":27428637,"url":"https://github.com/fvd/harper","last_synced_at":"2026-01-23T16:37:07.999Z","repository":{"id":71640081,"uuid":"190635189","full_name":"FvD/harper","owner":"FvD","description":"Harper: Lesson Discovery and Aggregation","archived":false,"fork":false,"pushed_at":"2019-04-17T20:41:01.000Z","size":72,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-14T13:53:02.208Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TSQL","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/FvD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-06T19:05:35.000Z","updated_at":"2023-10-12T08:15:54.000Z","dependencies_parsed_at":"2023-02-23T07:45:49.950Z","dependency_job_id":null,"html_url":"https://github.com/FvD/harper","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/FvD/harper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FvD%2Fharper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FvD%2Fharper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FvD%2Fharper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FvD%2Fharper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FvD","download_url":"https://codeload.github.com/FvD/harper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FvD%2Fharper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28695609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T15:57:05.722Z","status":"ssl_error","status_checked_at":"2026-01-23T15:56:27.656Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-14T13:39:06.856Z","updated_at":"2026-01-23T16:37:07.993Z","avatar_url":"https://github.com/FvD.png","language":"TSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Harper-Lite: Simple Lesson Discovery and Aggregation\n\nHarper's goal is better learning outcomes with less effort;\nHarper-Lite's is to get the ball rolling with as little effort as possible.\nIts design principles are:\n\n1.  Instead of building another repository or portal,\n    we will make it easier for teachers to make their lessons findable,\n    then aggregate the information they give us.\n2.  We will use tagging, voting, and direct online annotation\n    to provide feedback to lesson creators.\n3.  We will assume that people are going to adapt and remix material\n    instead of using it as-is.\n4.  We will not require people to be technically sophisticated\n    in order to comment, contribute, and collaborate.\n\n## Background\n\nHarper's design is shaped by:\n\n-   The success of RSS for decentralized content syndication.\n-   Mike Caulfield's analysis of [Stack Overflow][stack]\n    in terms of [choral explanations][choral-explanations].\n-   [This list][oer-landmines] of what has been learned from previous open educational resource (OER) projects.\n\nThe project is named after [William Rainey Harper][harper-william],\nfirst president of the University of Chicago,\nwho encouraged universities to offer distance education courses in the 1890s.\n\"Harper\" also happens to be the name of my youngest niece.\n\nI'm grateful to\nMike Caulfield,\nMine Çetinkaya-Rundel,\nNeal Davis,\nGarrett Grolemund,\nAlison Hill,\nAlyson Indrunas,\nFrançois Michonneau,\nBracken Mosbacker,\nNick Radcliffe,\nRaniere Silva,\nAlasdair Smith,\nJon Udell,\nand David Wiley\nfor comments,\nand to Peter Quill for show us that\n[you only need twelve percent of a plan][guardians-video] to save the galaxy.\nPlease see [this page](./harper-full.md) for a description of a larger and more complicated system.\n\n## Proposal\n\nTo make a lesson easier to find and re-use,\nauthors create one extra text file called `harper.yml` and put it in the lesson's root directory.\nThis single-file convention is inspired by the `feed.xml` and `feed.rss` files used for blogging,\nand by the `README.md` and `LICENSE.md` files now commonly used in software projects;\nwe use the name `harper.md` because Alasdair Smith pointed out that\nsome systems use `lesson.md` for the actual content of the lesson.\n\n`harper.yml` is formatted as YAML and must contain all of the fields shown below:\n\n```\nschema: \"harper-lite 0.1\"\ntitle: \"The Title of the Lesson\"\nabstract: \u003e\n  A single-paragraph summary of the lesson, the shorter the better.\n  It can be broken across multiple lines as shown here, and can\n  use [Markdown](https://en.wikipedia.org/wiki/Markdown) formatting.\nversion: \"1.3\"\ncontributor:\n  - \"Some Name \u003cemail@address\u003e\"\n  - \"Another Name \u003ctheir@address\u003e\"\npackage: http://package.url/lesson.zip\nlicense: http://license.url/\nrequirements:\n  R:\n  - \"package_1\"\n  - \"package_2\u003e=1.2.3.4\"\nprereq:\n  - \"Some learning objective.\"\n  - \"Some other learning objective.\"\npostreq:\n  - \"a glossary term\"\n  - \"a skill\"\nteaches:\n  - \"a term defined in this lesson\"\n  - \"a skill taught in this lesson\"\nnotes: \u003e\n  One or more sentences describing things instructors ought to know, formatted with Markdown.\n  For example, the notes could explain how long the lesson usually takes to do.\n```\n\n**Notes:**\n\n-   The `schema` field identifies this as Harper-Lite Version 0.1.\n-   The `title` and `abstract` fields should be self-explanatory.\n-   The `version` field is the version of the lesson (typically also the version of the package it's for).\n-   Contributors do not need to provide email addresses.\n-   The `license` value is the URL of the license rather than an abbreviation.\n    We will strongly encourage people to point at licenses at \u003chttps://opensource.org/\u003e.\n-   The `package` field is the URL for the downloadable lesson materials.\n-   `requirements` specifies any packages required,\n    organized under one sub-key per language,\n    using the syntax preferred by that language's default package manager.\n-   Learning objectives should be single sentences, each with an active verb,\n    describing something observable.\n-   The `prereq` and `postreq` fields are discussed below.\n-   `notes` is for anything else that might be helpful.\n\nThe `prereq` field is a list of terms or skills the lesson requires learners to have;\nthe `postreq` field is a list of terms or skills the lesson teaches.\nWe have used these rather clumsy names to avoid collision with `requirements`\n(which here means \"software requirements\").\nThe items under `prereq` and `postreq` are meant to be keywords, not full explanations.\nThese will be used to optimize search and to help people stitch lessons together\n(e.g., \"The lesson I want requires X---where can I learn about it?\").\n\nAn example of a Harper file is shown below;\n\n```\nschema: \"harper-lite 0.1\"\ntitle: \"Tests of Univariate Normality\"\nabstract: \u003e\n  How can we tell if univariate data is normally distributed?\n  This lesson describes three tests and explains the strengths and weaknesses of each.\nversion: \"1.3.1\"\ncontributor:\n  - \"Walter Bishop \u003cw.bishop@fringe.tv\u003e\"\npackage: http://stats.fringe.tv/stats454/normality/stats454-normality.zip\nlicense: https://creativecommons.org/licenses/by-nc/4.0/\nrequirements:\n  R:\n  - \"nickr (\u003e=1.2.3.4)\"\nobjectives:\n  - \"Describe the 68-95-99.7 rule and explain why it works and when it fails.\"\n  - \"Describe and apply the Shapiro-Wilk test for normality of univariate data.\"\n  - \"Describe and apply the ECF test for normality of multivariate data.\"\nprereq:\n  - \"Normal distribution\"\n  - \"Quantiles\"\n  - \"Statistical power\"\n  - \"Covariance matrix\"\n  - \"Empirical characteristic function\"\n  - \"Install R package\"\npostreq:\n  - \"`quantile`\"\n  - \"Kurtosis risk\"\n  - \"68/95/99.7 Rule\"\n  - \"Shapiro-Wilk test\"\n  - \"ECF test\"\nnotes: \u003e\n  This material was originally developed as part of a sequence on data integrity\n  for seniors and graduate students in statistics, then modified for delivery in\n  conference workshops.  The Shapiro-Wilk material feels pretty solid; the ECF\n  material has only been used a couple of times, and probably needs more work.\n```\n\n## Usage\n\nWe support collaboration with a voting mechanism like [Stack Overflow][stack]'s,\nbut with subject headings drawn from lessons:\n\n1.  An author registers a lesson by providing the URL to its Harper file,\n    just as someone can register a blog by providing a URL to an aggregator.\n\n2.  The site extracts data from the file and displays the lesson under each of `teaches` headings\n    to make it easier to find.\n\n3.  When someone views the page for a keyword,\n    they can provide comments on the lessons that appear there and upvote or downvote them.\n    This means that a single lesson could appear as the top \"answer\" for one keyword and the third \"answer\" to another.\n\n4.  We will provide an interactive upload mode:\n    after providing a URL for a lesson,\n    the author is walked through a very simple online form that asks for the information that goes in the lesson's Harper file.\n    We save that information and give it back to them to download and add to the lesson.\n    We still require that the Harper file be in the lesson's root directory as a check on authenticity:\n    allowing person X to describe a lesson created by person Y opens up too many opportunities for abuse.\n\n## Scenarios\n\n### How does an instructor find a lesson?\n\n1. She does a DuckDuckGo search for the word \"lesson\" and the keywords she's interested in.\n   If we've done our job right,\n   the lessons indexed by our site show up near the top of her search,\n   just as Stack Overflow answers show up near the top of a search for a technical question.\n2. She comes to our site and does a targeted search for her keywords.\n\n### How does an author register a lesson?\n\n1. They create a directory on their website with a meaningful name that includes a Harper file\n   and possibly a zip file containing starter materials (if the lesson's exercises need any).\n2. They sign into their account on our site and register the URL of the lesson directory.\n3. Our site validates their Harper file.\n\nAs noted above,\nwe don't allow people to register lessons that they don't control,\ni.e.,\nthey have to be able to add `harper.md` to the lesson's website in order for us to accept the registration.\n\nCritically,\nour site does some fuzzy matching to suggest rewording of terms\nto match ones in lessons that are already registered.\nThe term \"[folksonomy][folksonomy]\" seems to have lost its luster,\nbut encouraging convergence on a shared vocabulary seems crucial to making all of this work.\n\n### How does someone ask for a lesson?\n\nRather than waiting for people to register their own lessons,\nwe provide a \"please register this\" workflow:\n\n1.  Jeanne stumbles across a lesson she finds interesting.\n\n2.  She checks if there's a record of it.\n\n3.  If there isn't,\n    but someone before her has expressed an interest,\n    we add one to the \"wanna have\" count in our database.\n\n4.  If there isn't any record in our database,\n    we scrape the site to get contact info for the lesson's author, Vlad.\n    We then send Vlad a single message saying, \"Hey, someone's interested in your lesson.\"\n\n5.  Vlad will probably ignore the message,\n    but if he responds by creating a record for his lesson,\n    we stash that so that future inquiries will resolve\n    and notify Jeanne that the record is now available.\n    This workflow serves the triple purpose of attracting more authors,\n    not spamming them,\n    and ensuring that the record for a lesson comes from someone identified in the lesson's content\n    (i.e., probably not a disgruntled former student).\n\n### How does an author update a lesson?\n\n1.  They sign into their account,\n    go to \"My Lessons\",\n    and push the \"update\" button next to the lesson in question.\n\nNote that we archive past Harper files but not the actual lesson content.\n(We're an index not a repository.)\n\n[choral-explanations]: https://hapgood.us/2016/05/13/choral-explanations/\n[folksonomy]: https://en.wikipedia.org/wiki/Folksonomy\n[guardians-video]: https://www.youtube.com/watch?v=XC8qrH3Zwog\n[harper-william]: https://en.wikipedia.org/wiki/William_Rainey_Harper\n[oer-landmines]: http://third-bit.com/2018/12/02/oer-landmines.html\n[stack]: http://stackoverflow.com\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffvd%2Fharper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffvd%2Fharper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffvd%2Fharper/lists"}