ABACUS.PRG

2024-12-30 → 2025-01-17 · 54 commits · solo · PUBLIC

WHAT IT IS.

New Year's Eve, 2024: while everyone else was making resolutions, I was writing the merge primitives for a Spotify playlist tool — proof that a good diff algorithm is more satisfying than a countdown. The result is a React + Tailwind front-end that pulls a user's Spotify playlists into two synchronized columns and lets them diff, delete, move, clone, reorder and merge tracks across them. Operations are debounced and cached client-side in src/utils/operations.js, with a change ledger in src/utils/changesManager.js. Server-side (server/server.py, server/playlist_handler.py, server/chat_handler.py) is a thin Tornado stack speaking PKCE OAuth and proxying the Web API, plus a small handler that calls an LLM to suggest a playlist from a natural-language prompt. The build closes with server/Dockerfile (24 lines, head) and deploy.sh (5 lines, sanitised prod/dev envs). It is also the first project whose history explicitly records an LLM-assisted finish: the final commits are tagged "ChatGPT", "AI being requested", and "AI assistant," around the bridge between chat_handler.py and playlist_handler.py.

THE ARC.

Day one (Initial commit, 2024-12-30) is the whole scaffold: package.json, public assets, App.js, Callback.js, LoginButton.js, Playlists.js, the README — 19 files, 489 insertions, all in one commit. Hour two is Navigator.js (104 lines) and a .proxyrc.json so the dev server proxies to localhost:8888. Diff working (2024-12-31) is the first nontrivial refactor: Navigator.css plus 194 lines of JS, the synchronized-scroll seam between left and right lists. New Year's Eve (merging, All merge operations) close the diff/merge primitive set, then New Year's Day splits the 636-line Navigator.js into FilterBox, PlaylistActions, PlaylistDetails, PlaylistList, PlaylistSection, SongList, SongsSection and a useNavigatorState.js hook — the structural turn that the rest of the project rests on. By Jan 1 22:56 the project has Ops cached (all working) (713/466 across eight files).

Next day is the Tailwind rewrite (Introducing, 1035 insertions and 520 deletions across sixteen files), then a ten-day stretch of one screenshot-friendly fix after another — visual bugs, drop issues, deleteList, grid layout, on 401 goto /, loading all playlists, favorites, the Move client to folder rename pass. The closing week is the LLM integration: A server API to produce playlists with ChatGPT (246 insertions, four server files), AI being requested (to wrap up), AI assistant (3 files, 332/−228), and Added dockerfile (head, 24 lines). The generative feature sits above deterministic playlist operations rather than replacing them.

Stack chips: React 18 · Tailwind 3 (tailwind.config.js, postcss.config.js) · Prettier (.prettierrc) · useNavigatorState.js custom hook · changesManager.js change ledger · Tornado + PKCE OAuth (server/server.py) · server/chat_handler.py LLM bridge · Dockerfile + deploy.sh.

WHAT I LEARNED.

  • Two synchronized columns and a deterministic merge primitive made the comparison legible. The change ledger then gave each operation an inspectable record.

  • Debounced cached operations separate immediate local feedback from slower network synchronization; the change ledger keeps that boundary visible.

  • The useful division of labor was deterministic UI logic with a generative layer on top. Suggestions could remain suggestions because the tool still owned the operations.

  • Tailwind rewrites are a reset, not a refactor: 1035 insertions and 520 deletions in one commit, then Navigator.css (-298) and index.css (-672) deleted entirely in the next.

[ DEODORO ] > CODE / abacus EJECT → SHELF