Docup

How it works

Eight stages between a repository and a docs site

Docup is a pipeline, not a prompt. Each stage produces something the next one can check, which is why the output holds up.

Ingest

Only the files that matter

A run starts by reading the tracked branch at a specific commit. Lockfiles, build output, vendored dependencies and generated code are filtered out before anything is read, so the generator sees what a reviewer would open.

The repository is streamed into memory for the duration of the run and discarded when it finishes. Nothing from this stage is written to disk on our side.

Ingest · acme/relay@a3f9c1e
  • src/184 files
  • examples/6 files
  • README.mdkept
  • package.jsonkept
  • pnpm-lock.yamllockfile
  • dist/build output
  • node_modules/dependencies
  • src/generated/generated code

412 of 3,118 files kept · 2.1 MB of source

Analyse

A skeleton of the code, not a pile of text

Each file is parsed with tree-sitter into its exports, types, function signatures and the imports between files. The result is a graph of the codebase: which modules are entry points, which are internal, what depends on what.

That skeleton is what every later stage reasons about. It is small enough to fit in context whole, and precise enough to check names and signatures against.

Structure · 412 files parsed

src/client.ts

RelayClientcreateClient

src/retry/policy.ts

RetryPolicybackoff()

src/server/index.ts

RelayServer

src/signing.ts

sign()verify()

src/errors.ts

RelayErrorDeliveryError

Exports

1,284

Import edges

3,902

Entry points

4

Summarise

Bottom-up, cached by content

Files are summarised individually, then folded into module and package summaries. Each summary is keyed by the hash of its source, so an unchanged file is never summarised twice, on this run or the next.

This is what keeps sync cheap: a push that touches three files re-summarises three files and the modules above them, and nothing else.

Summaries · 409 reused, 3 rewritten
  • src/retry

    cached

    Exponential backoff with full jitter; RetryPolicy is immutable and cloned per event. Dead-letter after attempts are exhausted.

  • src/signing

    cached

    HMAC-SHA256 payload signing with a rotating secret. verify() accepts the previous secret for one hour.

  • src/client.ts

    changed in a3f9c1e

    Public entry point. Composes retry, signing and transport; the only class users construct directly.

Plan

An outline written for this codebase

A planner reads the package summaries and drafts the site: the guides this code actually needs, the reference pages that exist, and which sources each page should draw on. A library gets a quickstart and API reference; a service gets deployment and configuration guides.

Sections you rename, pages you pin and paths you exclude are respected here, so your choices survive every regeneration.

Outline · 14 pages planned
  • OverviewREADME.md, package.json
  • Quickstartexamples/basic.ts
  • Guides
  • Delivering eventssrc/client.ts
  • Retries and backoffsrc/retry/*
  • Signing payloadssrc/signing.ts
  • Reference
  • RelayClientsrc/client.ts
  • Errorssrc/errors.ts

Write

Each page from its own sources

Pages are written one at a time with only their planned sources retrieved into context, alongside the outline so cross-references point somewhere real. Every claim keeps the file and line it was drawn from.

Writing from retrieved source rather than memory is why the pages read as documentation of your code rather than of code like yours.

Writing · guides/retries.md

Retries and backoff

Relay retries failed deliveries up to five times by default src/retry/policy.ts:12, waiting between attempts with exponential backoff and full jitter src/retry/policy.ts:41. Once attempts are exhausted the event is moved to the dead-letter queue src/client.ts:88 and a DeliveryError is raised src/errors.ts:27.

retrieving src/retry/policy.ts · 2 of 4 sources

Verify

Checked against the skeleton before it ships

Every identifier in a page is looked up in the parsed code, every signature is compared with its declaration, every internal link is resolved against the outline, and code samples are parsed. Sentences that fail are rewritten with the correct source in view, or dropped.

The result is not perfect prose; it is prose that does not name functions that do not exist.

Verification · guides/retries.md
  • Identifiers exist in source214 / 214
  • Internal links resolve38 / 38
  • Code samples parse12 / 12
  • Signatures match declarations61 / 61

1 sentence rewritten

Retries default to three attempts. Retries default to five attempts. src/retry/policy.ts:12

Publish

A versioned site on the edge

The finished pages become a version. Publishing renders the site, builds the search index, writes the sitemap, llms.txt and a Markdown copy of every page, and puts it all behind your address.

Every publish is kept. Rolling back is a version switch, not a rebuild.

Publish · v14
Addressacme.docup.dev/relay
Pages14 published
Search indexbuilt · 1,930 terms
llms.txt, sitemap, Markdown copieswritten
Previous versionv13 · restorable
Live · served from the edge in 38 regions

Sync

Every push, only what changed

With the GitHub App installed, a push to the tracked branch starts an incremental run. Changed files are re-summarised, the pages that depend on them are found through the import graph, and only those pages go back through write and verify.

Projects in review mode land the result as a draft. Everyone else gets a new version published a minute or two after the push.

Sync · push to main
  1. Webhook received

    a3f9c1e · 1 file changed

  2. Summaries refreshed

    src/retry/policy.ts · 1 of 412

  3. Affected pages found

    Retries and backoff, RelayClient

  4. Pages rewritten and verified

    2 pages · 41s

  5. Published

    v15 · 12 pages unchanged

Data

What stays and what does not

Enough to keep the next run cheap, never the code itself.

Kept

  • Generated pages and their versions
  • The site outline and your edits
  • Per-file summaries keyed by content hash
  • Run metadata: commit, duration, pages

Discarded

  • Your source code after the run
  • Repository contents on disk
  • Anything from excluded paths
  • Installation tokens beyond their hour

Languages

Where the analysis goes deepest

Structural analysis needs a parser. Everything else still gets documented from the files, README and configuration; the reference pages are just less precise.

TypeScript, JavaScript
Full structural analysis
Python
Full structural analysis
Go
Full structural analysis
Rust
Full structural analysis
Java
Full structural analysis
Everything else
Documented from files and README

Start now, read the docs before you decide

Connect a repository and the first generation is on us. No card, no configuration files, nothing to install.