23

How Code Actually Reaches Production

From your machine to a live URL — what "shipping" actually means, stage by stage

"Shipping" isn't one action

People say "just ship it" like it's a single button. It's not — it's five distinct stages, and each one exists because the stage before it can lie to you. Code that looks right on your screen isn't the same thing as code running on a server the world can reach.

1
Commit

Save a labeled snapshot of your change to git's history — not the working files, the history.

2
Review

A second pass — human or AI — reads the change before it merges, because you can't see your own blind spots from inside the change.

3
Build

Turn source files into the actual thing that runs — checked, compiled, or bundled.

4
Deploy

Move the built artifact onto a server other people's browsers can actually reach.

5
Verify

Independently check the live URL. Not "it said success" — you personally confirm it's really there.

Every stage catches a different failure

A change can pass every stage before it and still fail the next one. Code that builds fine can still fail to deploy. Code that deploys fine can still be broken on the live page. That's why you don't skip stages — each one is looking for something the others can't see.

Commit and review: the paper trail

A commit isn't "saving the file" — you're already doing that. A commit is a labeled snapshot in git's history: this exact set of changes, with this exact reason, at this exact moment. That history is what makes every later stage possible — reviewers read it, rollbacks target it, and the build starts from it.

git add modules/23-how-software-ships.html
git commit -m "feat(dojo): publish module 23"
git push
Stage exactly the files this change touches — not everything sitting in the folder.
Write the message as a reason, not a description: why this change exists.
Push sends your local history to the shared copy — this is the first moment anyone else can see it.

Review is the deliberate second look before a change joins the main line. A colleague reading a pull request, or Claude Code running /code-review against a diff, does the same job either way: catch what's obvious to a fresh set of eyes and invisible to the person who just wrote it. Skipping review doesn't save time — it just moves the cost to whoever hits the bug in production.

Build: source isn't the product

The files you edit are rarely the files that run. A build step turns source into the real artifact — checking types, compiling, bundling, or in the simplest case just assembling plain files into their final shape. This dojo is a working example: its own build script reads every module file and generates the actual pages you're reading right now.

cd apps/dojo && bash build.sh
# → discovers modules/*.html
# → generates index.html + lessons/*.html
The build reads every source module and assembles the landing page + lesson pages from them.
It fails loudly if a module is malformed — that's the point. A build that always succeeds isn't checking anything.
A build that never fails isn't a safety net

The value of a build step is exactly the errors it's able to catch before a human sees them. Type errors, broken imports, malformed markup — a build that always says "success" regardless of what you fed it isn't verifying anything. It's just theater.

Deploy: putting it where the world can reach it

Deploy takes the built artifact and puts it on infrastructure with a public address — a server, a CDN, a static host. Before this step, "it works" only means it works on your machine. After this step, it means a browser anywhere can load it. This exact lesson reached dojo.ormus.solutions through the command below.

vercel deploy --prod --yes \
  --token $(cat ~/.credentials/vercel/ormus/api-token-edit) \
  --scope ormus-solutions
--prod means this replaces what's live right now, not a disposable preview link.
The token authenticates as you — never paste a live token into a file that gets committed.
--scope targets the right account. Deploying under the wrong scope is a quiet way to ship to nowhere.

Notice what deploy does not do: it doesn't tell you whether the page actually renders correctly. A deploy command returning "success" only means the file transfer succeeded — not that what's live is what you meant to ship.

Verify: trust nothing you didn't check yourself

This is the stage most people skip, and it's the one that actually matters. A deploy tool telling you "success" is a claim, not a fact. Verification means you go look — ideally with both a positive check (the thing you expect is there) and a negative check (the thing you don't expect is gone).

curl -s -o /dev/null -w "%{http_code}\n" \
  https://dojo.ormus.solutions/lessons/23-how-software-ships.html
# expect: 200

curl -s https://dojo.ormus.solutions/lessons/23-how-software-ships.html \
  | grep -c "How Code Actually Reaches Production"
# expect: >0
The first check: does the URL even resolve, with the right status code?
The second check: is the actual content there, not just a page that happens to load?
Same discipline, any stack

Swap curl for a browser click, an app store listing, or opening the app on your phone — the principle doesn't change. A tool reporting success is not the same as you confirming the result. That gap is where "it deployed but nobody can see it" bugs live.

Pipeline check

Three situations. Spot which stage is actually being tested.

Scenario

You've finished editing a file and want a permanent, labeled record of exactly what changed and why.

Which action creates that record?

Scenario

A module file has a typo that leaves an HTML tag unclosed.

Which stage is supposed to catch this before it goes live?

Scenario

Your deploy command finishes and prints "Deployment successful."

What's the correct next step?

Your move

Next time you ship anything — a script, a config change, a one-line fix — name the stage you're in out loud. Committed? Reviewed? Built? Deployed? Verified? If you can't answer "verified" with a URL you personally checked, you're not done yet.