Read the book first, in the barerepo/book repository. This file is the order
of operations.
Nothing here is mandatory, but each choice follows from a rule in chapter 5 of the book.
html/template
is sufficient. There is no build step, no bundler, no node_modules.[database] url picks which; see
chapter 41.7.1. SQLite is the default and is the right answer for almost every
install. Postgres exists for people who already run one.
Write against database/sql and keep the schema to what both dialects accept,
so neither one becomes the only one that is actually tested.git. Start by shelling out; it is
faster to get right and the process overhead is invisible next to network time.
Optimize only if profiling says so.? into $1 for Postgres.Each stage should be independently usable. Do not build stage N+1 until N works.
1. Git over ssh and http. Serve git-upload-pack and git-receive-pack.
Authenticate ssh by public key. At the end of this stage you can clone and push,
and nothing else exists. This is the whole product's foundation; if it is not
fast and correct, nothing above it matters.
2. Read-only web views. Log, file tree, file view with blame gutter, commit,
compare. No accounts yet, public repos only. Mockups: repo-log.html,
repo-files.html, repo-file.html, repo-commit.html, repo-compare.html.
Note the landing page is the log, not the file tree. Nobody navigates code by clicking folders. Every row on it is the same row: what changed, by how much, and a the hash as the link to it. No diff is drawn there.
3. Accounts. Signup, signin, keys page. Nonce challenge flow. Namespace
ownership. Mockups: signup.html, signin.html, keys.html, profile.html,
new-repo.html, repo-empty.html.
4. Proposals. The pre-receive hook that allocates refs/proposals/<n>. The
post-receive hook that detects reachability and closes. Compare view against a
proposal ref. Mockup: push-rejected.html. This page matters more than it
looks, because rejection is where new contributors get stuck.
5. Threads. Notes storage, union merge strategy, comment rendering, the
unified list. Mockups: threads.html, thread.html, thread-new.html.
6. Runners. Token issue and revoke. Runner protocol: the runner dials out and
long-polls; it never needs an inbound port, which is what makes "paste one line on
your laptop" actually work. Mockups: runner-setup.html, runners.html,
runs.html, run.html.
6A. GitHub workflows. Read .github/workflows when [build] command is
absent, translate the run: steps, and decline everything else by name. Match
runs-on against attached runners and point at the add-a-runner page when none
fits. Chapter 15A. The rule that makes it worth having is that a skipped step is
never silent.
7. Search. One index, one result set across code, threads and repos. Filter
every query against the requesting user's readable set, per chapter 17. Mockup:
search.html.
8. Feeds and the inbox. The event log, the inbox page, Atom output, feed
tokens. Nothing before this stage tells anyone that anything happened, so it is
not optional. Mockup: inbox.html.
9. The rest. Releases and artifacts, webhooks with the SSRF deny list, server
side copy, rename with permanent redirects, archiving. Mockup: releases.html.
Chapters 20 to 23A cover these; none of them changes anything below them.
This is the piece to get exactly right, because it is the most visible proof of the no-interstitial thesis.
curl -sL barerepo.sh | sh -s rt_live_7Kq2mXe
The token is in the copied line. There is no "now go to settings and paste this" step, no OS tab to click, no config file to create. One copy, one paste, the machine is attached and the page it was copied from updates.
Requirements:
keys.html.Treat these as build-failing thresholds, not aspirations. They are asserted in the test suite and are not shown to users.
| View | Time | Payload |
|---|---|---|
| Any page with no diff | under 10ms | under 15kb |
| Log | under 20ms | under 30kb |
| Any page | under 2kb JS | |
| Raw file content | separate host, or headers per 42.3 |
Diff rendering is the one genuinely hard case. Cache rendered diffs by blob pair hash; they are immutable, so the cache never needs invalidation.
master or main. Read the repo's HEAD. Some third-party
tooling assumes main; your own CI must not.