Field notes · Creative engineering
How I built
the globe
The dot sphere on the home screen looks like a shader team built it, but it is really five hundred spheres and a recipe. On this page I take it apart layer by layer in plain words, keep the maths out of the way, and then show the pipeline that produced the page itself: a handful of AI agents working inside a harness I built so that every step leaves evidence and every claim can be checked.
Specimen-001
dot-sphere · 500 nodes
running · webgl
Section 01
The honest dissection
A sphere is really a straight line of dots that learned to wrap, and my first attempt was exactly that: dot after dot on a flat line, then the line folded into rings. The poles ended up in a traffic jam, which is the same pile-up you get when you wrap a string around a ball by ear.
The fix turned out to be a walk you can do without opening a formula once. You start at the top pole and take equal hops down toward the bottom, one hop per dot, and every hop lands on its own meridian, a different direction around the globe than the one before. After five hundred hops the surface is evenly covered and nobody has crowded anybody, which still surprises me, because the whole trick is easier to explain at a dinner table than to write down.
That is the entire placement algorithm. A textbook calls this walk a “Fibonacci sphere”, and I only learned the name afterwards; I did not need it to build the thing, and neither do you.
“Every globe I saw on the web came from an off-the-shelf library wrapped in thirty megabytes of opinions. Mine is a spiral, because I wanted to earn every dot.”
A straight row: depth has no meaning yet
Wrap it in rings: the poles crowd up
The walk: one meridian per dot, even cover
Section 02
Inner workings: three layers
The three layers below pull their code straight from the component, the same snippets you would find in the repo. Click one and the specimen reacts: placement first, palette next, then the motion.
// 500 dots, no crowding. The recipe does the spacing:const dots = Array.from({ length: 500 }, (_, i) => {const phi = Math.acos(-1 + (2 * i) / 500); // pole → poleconst theta = Math.sqrt(500 * Math.PI) * phi; // 1 meridian eachreturn [5 * Math.cos(theta) * Math.sin(phi), // x5 * Math.sin(phi), // y5 * Math.cos(phi)]; // z})
annotation rail
Section 03
Inspiration: the GitHub globe
GitHub renders a globe on their homepage, and anyone who has put a planet in a browser has measured themselves against it at least once. So this is my accounting of it: what their build contains, and what mine kept.
Section 04
The pipeline: building with an agent harness
This is the part I care about more than the globe. The prompt I started this build with was a single line about wanting a globe like GitHub’s, but mine. Getting from that line to pixels that render accurately is a harness question, and mine works in three modes, explore, collaborate and delegate, with a verdict at the end. They are the same modes I argue for in “What are we trying to augment?”, pointed at a canvas instead of a chat window.
- 01
Explore
It starts with an intent check instead of a task dump. The prompt was one line, "a globe like GitHub’s, but mine", and the agent replied with questions instead of code: what should it feel like, who is it for? Answering them put the reasoning on the record early.
- 02
Collaborate
The harness pushes back before it builds. It proposed a shader that would have fit in forty lines; I wrote back "then I would own the maths again" and we settled it with three design sketches. The sketches are the minutes of that argument.
- 03
Delegate
Now the agents build on a leash. Their tools are the repo, the dev server and a browser, every call is logged, and the harness blocks the expensive moves like pushing to main. Nothing merges until I have read the diff myself.
- 04
Ground truth
The loop is small enough for a napkin: edit, reload, screenshot, compare, roll back when in doubt. It ran about thirty times on this build and always ended the same way, with the pixels telling me whether the reasoning held.
- 05
Verdict
Types, lint and tests get the last word. If a shot goes dark the harness bisects on its own until the culprit is cornered, and the reasoning that found it is saved right next to the verdict.
Delegate is the mode nobody trusts until they watch the verdict step work. A screenshot cannot flatter you. One evening the shots went dark on this build, and the first two explanations, animation timing and React hydration, were both wrong; it took three fresh browsers, one git stash and the untouched baseline before the real cause showed itself, a physics wrapper that had been simulating an empty world the whole time. The agent that pinned it down did not guess. It bisected.
Explore, collaborate, delegate, then let the evidence speak: that loop is what I mean by an AI harness, a pipeline with instruments on it. What made it feel like the essay rather than a toy was the learning path. Before the harness hands over a fix it asks what I suspect, so the hypothesis goes on the record even when it is wrong; the sketch arguments forced me to defend taste out loud; and by the time the agents were typing, the judgement was mine. The globe is ninety lines of code. The harness around it is the actual product, and it is built to leave me more capable than it found me.
$ harness run --prompt "a globe like github's, but mine" > intent: create, visual, maths kept out on purpose > explore: 3 questions asked back, answers on the record > tool: sketch ✓✓✗ "denser near the equator, softer dots" > collaborate: shader rejected -- "then I own the maths again" > delegate: tools = repo · dev-server · browser, push denied > loop ×28: edit → reload → screenshot → compare → keep/rollback > verify .... buf: [644, 594] context dead $ git stash → original buf: [652, 652] context alive + physics wrapper buf: [644, 594] context dead + palette copy buf: [644, 594] context dead > THREE.WebGLRenderer: Context Lost. > culprit: <Physics> -- empty world, removed. > verdict: PASS · 30 loops · I can defend every line