LLMs mimic Studio Ghibli art. What if they mimic-ed developers? And solved a SINGLE problem in their styles? Can we learn from that?
I picked a five-step checkout state machine problem:
createCheckoutMachine() → { state, send, allowed, subscribe }.
idle → cart → address → payment → done
.NEXT
moves the state forward. BACK
moves backwards. FAIL
on payment
goes to address
.I had ChatGPT identify famous JS developers and used Codex CLI to write code in each developer’s style (“Write in the style of $DEVELOPER.”)
Here is the result:
Developer | How their code works |
---|---|
addyosmani | Code used a transitions “table” of functions to get the next value. He calls allowedFor(state) before computing next to validate. That’s a clean separation of can I? vs do it. |
antfu | Code used a graph object that maps each state to its next states. He implements allowed() as Object.keys(graph[current]) to list valid events for the current state. That keeps branching low and makes the code friendly to edit. |
davidkpiano | Code used a small helper shift(delta) to move forward or back through the steps. He then dispatches via a transitions map of tiny functions. That reads like a compact, explicit state machine. |
developit | Code wrote straight-line, imperative code with a tiny move(next) helper to change state. He hand-wrote the allowed() cases for clarity. It’s very easy to skim. |
evanw | Code returned a compact api object and used optional chaining on the graph lookups. He calls notify(state) with the new state, which leaves room to extend notifications later. It feels neat and tooling-like. |
jarred-sumner | Code inlined almost everything for speed, but he does not validate initial . With an invalid initial state, a BACK event can set state to undefined (because steps[index-1] with index=-1 becomes undefined ) and then notify subscribers with undefined . It’s fast, but has sharp edges. |
kentcdodds | Code defined a clear allowedMap , plus small move(next) and notify() helpers. The surface area is gentle and test-friendly. |
lukeed | Code kept a micro-library feel and first guards with allowed().includes(evt) . He does not normalize initial . That’s mostly safe: the first NEXT snaps to 'idle' , while other events are blocked. |
mbostock | Code based everything on an index and updates via update(nextIndex) and avoids re-looking up allowed events. He also kept separate allowedEvents . It’s very explicit, diff-friendly, and avoids recomputing work. |
paulirish | Code extracted a pure nextState(state, event) function. He also kept a mutable machine.state field in sync with the internal state . That matches the target TypeScript shape, but it’s a foot-gun: consumers can assign machine.state = 'done' and desync things. |
rich-harris | Code wrote a direct, branchy send with a tidy notify() call. He listed allowed() explicitly per state. The result is clear and compiler-friendly, with no indirection. |
ryansolid | Code used two maps—flow for forward and trail for back—so NEXT /BACK never need indices. He drives allowed() from an options map. It’s nicely decomposed. |
sebmck | Code used a compiler-style flow graph and returned a single api object. He relied on optional chaining and key lookups. It’s cohesive and tersely “tooling”. |
sindresorhus | Code added tiny helpers (STEPS , indexOf ) and gated with allowed() early to keep branching minimal. It feels like a sharp utility. |
tannerlinsley | Code paired an allowedMap with a setState(next) helper that both updates and notifies. That makes the internal API ergonomic. |
Some common patterns:
Set
for subscribers and call each subscriber on change, and once on subscribe.get state(){...}
to prevent external mutation.initial
to ensure initial state is OK.Some differences:
antfu
, evanw
, sebmck
(and close cousin ryansolid
, who splits forward/back maps). E.g. graph[state]?.[event]
, allowed()
= Object.keys(graph[state])
. Easier to add/branch events. Great for non-linear flows.addyosmani
, davidkpiano
, developit
, rich-harris
, sindresorhus
, tannerlinsley
, kentcdodds
, mbostock
, paulirish
, lukeed
, jarred-sumner
. E.g. steps.indexOf(state)
; NEXT/BACK via ±1
. Minimal for linear flows. Fewer objects.allowed
map, e.g. mbostock
, kentcdodds
, tannerlinsley
, paulirish
, ryansolid
. A stable “allowed” policy makes testing and refactors safer.allowed()
to prevent consumers mutating the returned list. Subtle but solid API hygiene and a professional touch.jarred-sumner
and lukeed
, skipped input state normalization. That means that:
jarred-sumner
: a BACK
event on an initial
state ⇒ undefined
state.lukeed
: an invalid initial
ignores until NEXT
, then snaps to 'idle'
. (Safer than Jarred’s).By studying the masters, we learn a lot about how to approach a problem.
But with LLM style transfer, we no longer need masters to learn from their work. We can apply all their methods to any problem.
To me, that’s staggering!
I asked Codex CLI (gpt-5-high
) to suggest an expert to refactor my AIPipe repo.
Why use a generic coding agent when it can write in an expert’s style?