April DevLog
Building an experimental app to make the process of creating departmental budgets more fun. It’s a goofy idea to combine drudge work with a video game.
Summary:
This day was all about a complex and frustrating large-scale refactor of a budget management application. I was wrestling with moving the app to a single source of truth for budget item structure using OpenAI's Structured Outputs. The technical goal was clear: define the schema in one place and use it across the app. But the actual process revealed deep architectural debt, fragmented logic, and an unpredictable cascade of bugs. I leaned heavily on AI to assist, but often found myself battling inconsistent responses and rule violations. The refactor was a grind, marked by careful debugging, rule enforcement, and a pattern of the AI fixing one bug and creating another.
A key learning is that the sooner I jump into the code, the better the outcomes.
---
Building Better Get Done: Bugs, Budgets, and Breakthroughs
Project: Better Get Done
Dates: 2025-04-11 to 2025-04-29
Summary:
This month, I went deep into building and debugging a complex React + Python application called Better Get Done — a hybrid escape room game with a budgeting twist. The app involves a spooky surveillance-style security interface and a gamified budgeting assistant powered by OpenAI’s Agents SDK. I worked across both the frontend and backend, implementing features like budget previewing, chat-based budget item entry, and structured data persistence via localStorage. I also fixed dozens of bugs, sometimes introduced by the AI, and made the system more modular and robust. The debugging sessions were intense, but the architecture came together in a clean, powerful way.
Backend: Python API, OpenAI Agents, and Data Flow
I migrated the app’s backend to Python using FastAPI and structured it as a monorepo. The server auto-detects an open port and exposes endpoints used by the frontend chat system. I integrated the OpenAI Agents SDK and built multiple agents, including ones for IT, HR, and Business Unit budgeting. I also refactored the /api/chat/
endpoint to use OpenAI’s new responses
API mode instead of chat completion, handled streaming and non-streaming responses, and ensured proper markdown rendering in the results.
Each budget conversation is persisted in localStorage. When the user clicks "Submit Budget & Escape", the structured budget data is pulled from localStorage and sent to the CFO review endpoint. The response is shown in a modal, not the chat window.
I also built out the system prompt ingestion flow with environment variables and .env
loading via python-dotenv
, ensuring API keys and system prompt text were managed cleanly. I made sure all backend changes respected the game’s architecture and avoided unnecessary API calls, especially for things like rendering the budget preview.
Frontend: React, Chat UI, and Spreadsheet-Style Budget Preview
I overhauled the frontend to feature a persistent chat interface using the assistant-ui
component library. The chat now supports markdown, structured JSON parsing, and differentiates between web search and regular chat responses. When the assistant returns structured budget items, they are parsed and added to a localStorage-backed set. This set is then rendered in the Budget Preview tab as a table, complete with editable cells, delete buttons, and downloadable CSV export.
I restructured the tab navigation to make the UX more consistent. Instead of modal previews, the Budget Preview now lives in its own tab. I also added a "Clear Budget" button that fully clears localStorage and resets the UI—without restarting the game.
The BudgetPreviewTab was made more modular: I extracted the CSV export logic into a shared utility, moved helper functions to budgetColumnUtils
, and centralized config keys like budget_items_set
to avoid hardcoding.
Local Storage: Persistence and Data Consistency
Much of the work focused on ensuring consistent use of localStorage. Any structured response returned by the assistant is now parsed and saved as part of the budget item set. Edits to individual cells in the preview table are reflected back to localStorage immediately. I added logic to prevent duplication and ensured that deletions and modifications are always tied to the correct itemId
.
I created utilities for generating UUIDs for new items, wrote functions to get/set/delete items from the budget set, and made sure these are used consistently across all components including useBudget.ts
, BudgetDeskChat.tsx
, and budgetItemsService.ts
.
Bugs and Refactoring: A Lot
There were dozens of bugs. Characters weren’t moving correctly. The chat wasn’t persisting. The budget preview was out of sync. Markdown wasn’t rendering. Double-click editing broke. Static effects were inconsistent. Items weren’t being saved. Items weren’t being deleted. The game restarted when it shouldn’t. I tracked them all down and fixed them methodically.
In many cases, I had to revert AI-suggested changes and do a manual analysis. When needed, I asked the AI to create mermaid diagrams to track data flow, character movement, or the budget item lifecycle. These visuals helped clarify architectural decisions and spot issues in logic.
Game Mechanics: Animatronics and Surveillance
I also spent time refining the escape room mechanics. Characters (the CFO, Comptroller, and Accountant) move through locations based on proximity and timers. Each character has a home location and a synchronized 15-second timer that starts when all characters are home. If the timers expire, there's a chance that characters move. The player must find them using the camera feeds and click “Working on it!” to send them back.
I fixed bugs where multiple characters appeared in a single location, or where the “Working on it!” button didn’t behave correctly. I also ensured that the correct images are shown depending on the state of each character—whether active, leaving, or at home. The logic is now cleanly centralized using functions like getAnimatronicImage
.
Architecture: Documented and Modular
I formalized the architecture with a high-level design doc that captures the split between the game (React) and the budgeting (Python + OpenAI). I documented the API flow, the structure of localStorage, and the logic for character state transitions. I also made the game more robust by consolidating image rendering logic and centralizing style rules.
All in all, this was a massive sprint of architecture, debugging, and refinement. Better Get Done is now a functional, immersive, and technically solid experience.
(written by Cursor Journal)