TeXPRs
LaTeX lives in Git, but a pull request only shows you the source. Swap github.com for texprs.com in any PR link and you get the compiled PDF before and after, side by side, overlaid, or with every change marked up. No cloning, no checking out branches.
TeXPRs came out of my capstone. Our team of five writes every deliverable — the problem statement, the SRS, the hazard analysis, the design documents — in LaTeX, in one GitHub repository, and every change goes through a pull request. Reviewing one means reading a diff of LaTeX source. To see what the document actually looks like, somebody has to pull the branch, compile it and open the PDF, which in practice meant most reviews were approved from the source alone. Before building anything I looked for a tool that already showed the PDF on the pull request itself. There are GitHub Actions that compile a document and upload it as an artifact, and editor extensions that run latexdiff locally, but nothing that puts the rendered document in front of the reviewer.
The first decision was the shape. A Chrome extension would have needed installing on every reviewer's machine, and a GitHub Action would have needed setting up in every repository. A website needs neither, and it can reuse GitHub's own addresses: the path for a pull request is identical on both sites, so turning github.com/owner/repo/pull/12 into texprs.com/owner/repo/pull/12 is the whole interface. That is where the name comes from.
It runs as two halves because the web half cannot compile anything. A full TeX Live install is several gigabytes and Vercel functions have size and time limits, so the Next.js site on Vercel does GitHub sign-in and the reading of the pull request, and a separate compile worker does the LaTeX: a small Hono server in a Docker image with a trimmed TeX Live, latexmk and latexdiff, running on Fly.io in Toronto and sleeping when nobody is using it. The page never sends PDFs through Vercel. It hands the browser an encrypted, expiring ticket for each document, and the browser fetches the PDF straight from the worker, so a thesis full of figures or a compile that takes most of a minute never hits a function's limits.
Most of the engineering went into the fact that compiling someone else's LaTeX is running someone else's code. \write18 runs shell commands, a latexmkrc file is Perl that latexmk executes, and \input will happily read files outside the project. So shell escape is off, TeX may not write outside the project, latexmkrc files are deleted and latexmk runs with -norc, symlinks are stripped after unpacking, the archive is measured before it is extracted, and every compile has a time limit. The first version also refused any path containing "..". Then I pointed it at our capstone repository and every document failed, because the course template has each one \input{../Common.text}. Reads outside the folder had to be allowed, so the isolation moved down a level: each concurrent job now runs as its own unprivileged user in a folder only that user can open, which keeps it away from the server's secrets and from any other job's checkout, possibly someone else's private repository.
The other thing real use found was GitHub's rate limit. Signed-out visitors get 60 API calls an hour, and the first version spent about thirty on a single page load, mostly reading .tex files to find which one was the document. It stopped working after two refreshes. File reads moved to raw.githubusercontent.com and archive downloads to codeload, neither of which counts against that limit, and anything addressed by a commit hash is cached per user because it cannot change. A page load now costs five calls.
The part I would point to is the test suite rather than any one feature. Thirteen checks compile real fixtures inside the production image on every push: an ordinary paper with a bibliography, a XeLaTeX document, a broken one, the capstone layout, and a set of deliberately malicious documents that try to run a command, write outside the project, read the server's environment through a symlink, and read another job's files. A sandbox is only as good as the attacks it has actually been shown to stop, and both of the bugs that mattered most were found by pointing the thing at my own team's repository rather than at examples I had written.
A walkthrough on a real pull request from my capstone team's repository: swapping github.com for texprs.com, then the marked-up changes and the two versions side by side.