apps/github-clone, name github) is an API-only clone of
the GitHub REST API: a NestJS backend on Postgres
that reproduces GitHub’s core repo-collaboration surface — users/orgs,
repositories, issues, pull requests, comments, labels, milestones, branches, and
commits — using real GitHub conventions: bare resource paths
(/repos/{owner}/{repo}/…, /rate_limit), bare-JSON bodies (no wrapper),
page+per_page pagination via an RFC-5988 Link header, integer id +
node_id on every object, a {message, documentation_url} error envelope, and a
GitHub-style rate limiter. It’s faithful enough at the URL + wire-format
level that an agent built for GitHub can operate it.
Routing — read this first
Real GitHub serves its REST routes at the root (/repos/..., /user,
/rate_limit), with no /api prefix. So the backend uses no global prefix:
data-plane controllers bind bare GitHub paths, while the clone’s own
control-plane routes keep an explicit /api segment so they never collide with
GitHub’s namespace.
What’s inside
Modes
This template is API-only — there is no frontend.
Seeding
users, repositories, and issues (the template’s
declared entities) through real signup/repo/issue calls. See
Seeding.
Tokens and auth
Every data route is guarded by default (a globalAuthGuard); @Public() opts
out (/api/auth/*, /api/health). The clone authenticates two ways, both as
Authorization: Bearer … (the ghp_ path also accepts token ghp_…):
- a JWT access token from
POST /api/auth/signup/login/refresh(the web path), and - a GitHub-shaped personal access token (
ghp_…) minted atPOST /api/user/tokens. Onlysha256(token)is stored; the plaintext is shown once at creation.
password123 (e.g. octocat@acme.test).
A
ghp_ token authenticates but its scopes are not enforced — any valid
token can call anything. Scope enforcement, GitHub Apps / OAuth installs, and
fine-grained tokens are out of scope for this slice. Reads currently require a
token (real GitHub serves public GETs anonymously). Clones bind to localhost by
default, so a token is not reachable off your machine unless you --expose.API tour
Pagination
List endpoints takepage (1-based, default 1) and per_page (default 30, max
100), return a plain JSON array (no wrapper), and set an RFC-5988 Link
header (rel=next/prev/first/last), CORS-exposed. Like GitHub, there is no
X-Total-Count header — the Link header is the only pagination signal.
Rate limiting
A global rate limiter mirrors GitHub’s: 5,000 requests/hr authenticated, 60/hr unauthenticated (per-IP), on a fixed 1-hour window. Every response carriesx-ratelimit-limit / -remaining / -used / -reset / -resource
plus x-github-api-version and x-github-media-type. Exhaustion returns 403
with a retry-after header. GET /rate_limit reports the live budget as
{ resources: { core, search, graphql, … }, rate }.
API shape — read this before pointing an agent at it
Because GitHub is a REST API, the clone matches it at the URL and wire-format level for the implemented slice, not just the capability level:- bare resource paths (
/repos/{owner}/{repo}/…,/rate_limit) — no/apiprefix on the data plane, - addressing by
login,{owner}/{repo}full name, per-repo integernumber, integercomment_id, labelname, and commitsha— never the internal UUID, - a numeric
idplus a base64node_idon every resource object, - bare-JSON bodies (no envelope) and the
{message, documentation_url}error envelope; 422 validation failures carryerrors[]of{resource, field, code}, Link-header pagination and thex-ratelimit-*budget headers described above.
number sequence, exactly like
GitHub — numbers never collide within a repo.
The template ships an API_PARITY.md that maps each implemented route to GitHub’s
live REST docs. The implemented core spans users, orgs, repositories, issues
(incl. lock/unlock), pull requests (incl. files, commits, is-merged, merge),
issue comments, labels + issue-label assignment, milestones, branches, commits,
and rate-limit — roughly 50 endpoints, with shape parity at 49/50 against
GitHub’s live docs. Whole GitHub families outside the core collaboration surface
(Actions, Checks, Search, Releases, Gists, Webhooks/Events, Git database
internals, reviews, reactions, projects, GraphQL v4, and the official MCP server)
are unimplemented by design — this is a vertical slice, not the full API. See
apps/github-clone/API_PARITY.md for the per-route breakdown.
The
verify command will fold live fidelity scoring into
the CLI. Until then, API_PARITY.md and the /verify-api github workflow are how
fidelity is tracked.Inspect a running clone
001_initial_schema.sql —
read it to know what’s queryable.