{"id":50568599,"url":"https://github.com/leanprover/comparator-live","last_synced_at":"2026-06-04T17:00:26.492Z","repository":{"id":362355541,"uuid":"1258663838","full_name":"leanprover/comparator-live","owner":"leanprover","description":"An online live.lean-lang.org-style playground for running the Comparator tool","archived":false,"fork":false,"pushed_at":"2026-06-03T21:04:03.000Z","size":177,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-03T22:06:33.045Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leanprover.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-03T19:52:02.000Z","updated_at":"2026-06-03T19:54:53.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/leanprover/comparator-live","commit_stats":null,"previous_names":["leanprover/comparator-live"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/leanprover/comparator-live","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fcomparator-live","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fcomparator-live/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fcomparator-live/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fcomparator-live/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leanprover","download_url":"https://codeload.github.com/leanprover/comparator-live/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leanprover%2Fcomparator-live/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33914548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":"2026-06-04T17:00:23.452Z","updated_at":"2026-06-04T17:00:26.486Z","avatar_url":"https://github.com/leanprover.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sourdough\n\nThis template project is part of Sourdough, a set of JavaScript templates that\nwere originally developed at Northeastern for their Software Engineering class\nin spring of 2026.\n\n## Vite+Express Full-stack React Application with Workspaces\n\nThis project has three parts, which together form an\n[npm workspaces](https://docs.npmjs.com/cli/v8/using-npm/workspaces) project.\n\n1.  A minimal Express transcript API for a very simple transcript server (in\n    the `./server` directory)\n2.  A Vite frontend for a simple React application that uses the API server\n    (this lives in the `./frontend` directory)\n3.  Shared Zod validation and type definitions (in the `./shared` directory)\n\nThe shared Zod validation is why the move to workspaces is desirable in the\nfirst place: it's common practice to keep frontend and backend code separate\nand to define a separate project that acts as a \"single source of truth\" for\nthe API's types and that is subsequently imported by both frontend and\nbackend. Zod validators and shared types are one of the most common things\nthat a project might share between the frontend and the backend.\n\nThe way this project runs in \"production mode\" versus \"development mode\" is\nvery different.\n\n### Production Mode\n\nProduction mode is simpler: there's one server running, the Express server, on\nport 3000, accessible via the url \u003chttp://localhost:3000\u003e. When a GET request\ndoesn't match any existing API endpoints, the Express server looks in\n`./frontend/dist` to see if there's a file it can serve from that directory.\nFiles are put in that directory when `npm run build` calls the `vite build`\ncommand.\n\nThe `vite build` step is necessary because we're writing our frontend code in\nTypeScript, but browsers can't do type stripping like Node can — we have to do\nsome transformation on the code we're writing to make it browser-friendly.\n(Vite is doing a bunch of other transformations for other reasons as well.)\n\n### Development Mode\n\nDevelopment mode is a little trickier to explain. When developing, we want our\nbrowser to be connecting to Vite's \"development web server\", not to Express,\nbecause Vite does a lot of nifty stuff to make sure that when we change our\nTypeScript code, it **reloads the web page**. That is _very_ handy for\nfrontend web development.\n\nHowever, this means your \"frontend code\" — the HTML and JS that the browser is\nsupposed to run being served by the Vite development web server — is coming\nfrom a different server than the Express server that's handling API requests.\nThe default convention is that Vite development web server is accessed via\n\u003chttp://localhost:5173\u003e, and the Express API server is accessible via\n\u003chttp://localhost:3000\u003e. If you try to have a website that is being served\nfrom a different website than the API service it is using, you're going to\nhave to gain a nightmarish amount of literacy with\n[CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS). (A\ndifferent port on `localhost` counts as a different website.) This wasn't a\nproblem in production mode: your entire website is coming from the Express\nserver. You really want your website to look like it's _all_ coming from a\nsingle server during development too.\n\nThe easy way to do this is to have the development server _only_ respond to\nAPI requests, and have the Vite development server forward all API requests to\nthe Express server. This is called \"proxying\", and it means that you can\naccess a complete Vite server from \u003chttp://localhost:5173\u003e. (The Vite\ndevelopment server needs to know what an API request is: it's configured to\ntreat every route starting with `/api` as an API endpoint.)\n\n### Express API\n\nThe Express server's API has the following endpoints:\n\n| Endpoint             | Method | Description                         |\n| -------------------- | ------ | ----------------------------------- |\n| `/api/addStudent`    | POST   | Add a new student                   |\n| `/api/addGrade`      | POST   | Add a grade for an existing student |\n| `/api/getTranscript` | POST   | Look up information for a student   |\n\n## Base configuration\n\nThe base project configuration follows a philosophy of \"minimalism, mostly.\"\nProject configuration should be minimal and have a bias towards implicit\ndefaults. Deviations from this principle should be justified and documented\n(here or elsewhere).\n\nNotable exceptions to this principle:\n\n- `.gitignore` takes a kitchen-sink approach and should freely accept\n  additions. (For example, if a student accidentally checks in a file that\n  could have been ignored, it makes sense to add that file here.)\n\n- The ESLint configuration is a maximalist attempt at keeping new TypeScript\n  programmers on the rails in a complicated codebase, and also giving them a\n  sense of working inside style conventions of a project that may differ from\n  their own.\n\n- If we can have all project variants using the _exact_ same `tsconfig.json`\n  file or `eslint.config.mjs` file by adding a bit of cruft to the base\n  configuration, that's a reasonable trade. Things are going to inevitably get\n  copy-pasted, and so the fewer copies of configuration files there are, the\n  better.\n\n  This is why the `.vscode/settings.json` applies Prettier to html and css\n  files even though that's not relevant to the base project, and why\n  `eslint.config.mjs` includes React's Rules of Hooks despite most of the\n  project variants not including any React code.\n\n### NPM Scripts\n\nThis sets up a set of commands that projects should consistently support, when\nappropriate:\n\n- `npm run check` runs TypeScript\n- `npm run lint` runs ESLint, and `npm run lint:fix` runs eslint with the\n  `--fix` option\n- `npm run prettier` checks formatting, and `npm run prettier:fix` writes\n  formatted files back to disk\n- `npm run test` runs appropriate tests on all projects: vitest without\n  coverage for the shared project (it's mostly validators and types anyway),\n  vitest with coverage for the API server, and Playwright end-to-end tests in\n  the frontend project that exercise the frontend and backend together\n- `npm run playwright` runs the Playwright end-to-end tests with the\n  interactive Playwright UI\n- `npm run dev` starts a development server or watch process\n- `npm run build` prepares the project for production-style deployment\n- `npm start` runs the project in production mode\n\nThese are tested by github actions in `.github/workflows/main.yml`.\n\n### ESLint\n\nThis base project has an opinionated ESLint configuration that relies on\n[typed linting](https://typescript-eslint.io/getting-started/typed-linting).\nThe ESLint configuration makes some assumptions about project structure:\n\n- Frontend code is code that lives in `./frontend` or `./client`, and\n  optionally uses React and JSX. This code is subject to different linter\n  rules.\n- Test code lives in a `**/tests` directory OR has a `*.spec.ts(x)` or a\n  `*.test.ts(x)` filename. Tests can use devDependencies, unlike other code.\n- Config files all have `*.config.mjs` filenames (vite, vitest, playwright,\n  and eslint all can follow this convention). Config files can also import\n  devDependencies, like tests but unlike other code.\n- Most everything should be registered as `error`. Warnings don't fail CI\n  checks. Exceptions should have a documented reason. Notable exceptions where\n  we either turn on warnings or leave the warn default in place:\n  - `no-console` is `warn` because no-console regularly gets turned off by\n    line or file specific rules: we want to discourage excessive `no-console`\n    use but it is more like the admonition to not check in commented-out code:\n    it's mostly a problem when done excessively and it's easy to check in\n    visual inspection.\n  - `prettier` is `warn` because red squigglies for `prettier` are especially\n    distracting and we can check for prettier failures in CI separately.\n  - `simple-import-sort/imports` is `warn` — it's a property much like\n    prettier in that it's a mechanical fix and the red squigglies are\n    extremely distracting. It's also no huge loss if this doesn't get flagged\n    in CI.\n  - We do not override the default setting of `warn` for\n    `react-hooks/exhaustive-deps` in the default configuration. This rule\n    makes the (horrible) suggestion to remove the dependency array, and people\n    breaking their projects by blindly following that suggestion would be a\n    bad outcome.\n\n### TypeScript\n\nTypeScript is configured with options that support\n[type stripping](https://nodejs.org/api/typescript.html#type-stripping).\nBeyond this, the TypeScript configuration enables\n`noFallthroughCasesInSwitch`, `noImplicitOverride`, `noImplicitReturns`, and\n`noUncheckedIndexedAccess`, which are linter-like properties that don't seem\nto be well-supported by typed linting in ESLint.\n\n[Matt Pocock's cheat sheet](https://www.totaltypescript.com/tsconfig-cheat-sheet)\nis a reasonable source for more on minimal typescript configuration.\n\n### Prettier\n\nThe `.prettierrc` file is intended to use some reasonable defaults. A\n`.vscode/settings.json` file is added to encourage Visual Studio Code to treat\nPrettier as the default formatter for javascript, typescript, json, css, and\nhtml files even if a students' global configuration uses other defaults.\n\n### LF Line Endings\n\nThe `.prettierrc`, `.gitattributes`, and `.vscode/settings.json` files\nconspire to generally force projects to use `\\n` file endings instead of\nWindows-style `\\r\\n` line endings (LF instead of CRLF).\n\n## Project Tree\n\nThe various Sourdough starters live in a single git repository as a series of\nGit branches that build off of one another.\n\n- [`base`](https://github.com/robsimmons/sourdough/tree/base), the base\n  configuration\n- [`express`](https://github.com/robsimmons/sourdough/tree/express), adds an\n  Express server and API tests\n- [`fullstack`](https://github.com/robsimmons/sourdough/tree/fullstack), adds\n  a Vite frontend (+ Playwright end-to-end tests) for a simple client/server\n  setup\n- [`fullstack-react`](https://github.com/robsimmons/sourdough/tree/fullstack-react),\n  makes the Vite frontend use React\n- [`workspaces`](https://github.com/robsimmons/sourdough/tree/workspaces),\n  uses NPM workspaces to mediate validation and types that can be productively\n  shared between the frontend and backend\n\n## Using Sourdough as a Starter\n\nThe `main` and `fullstack-react` branches should coincide, so you can use\nGitHub to fork the full-stack React project by just forking this repository.\n\nFor other branches, or if you don't want to deal with the weirdness of being a\nforked GitHub project, you'll want to follow a pattern like this, replacing\nthe three bits in square brackets as needed:\n\n```sh\ngit init\ngit branch -M main\ngit remote add upstream git@github.com:robsimmons/sourdough.git\ngit remote add origin git@github.com:[MY_USERNAME]/[MY_PROJECT].git\ngit fetch upstream\ngit merge upstream/[THE_STARTER_YOU_WISH_TO_FORK]\ngit push -u origin main\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fcomparator-live","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleanprover%2Fcomparator-live","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleanprover%2Fcomparator-live/lists"}