Apr 20, 2026
Inheriting a production app
When I joined Teams Squared, I inherited two key software projects from my predecessor: an internal cybersecurity posture reporting tool and an unreleased client dashboard app. Other legacy prototypes were on the table, but we deprecated them to focus entirely on building tools that directly drove company operations.
The client dashboard was not yet live—there were no active users, but there was an ambitious vision and a codebase I had never seen.
Getting that application over the finish line and into real production turned into one of the most intense, humbling, and educational software engineering experiences of my career.
From client viewer to complete internal platform
Originally, the app was designed as a lightweight client portal. Clients could log in to check the status of their engagements with Teams Squared, view active team members, and check due invoices and notifications. To populate this, the app pulled timesheets and leave requests via APIs and scraping from the third-party platforms we were already using—primarily Zelt for HRIS and Clockify for time tracking.
As we evaluated our operational needs, the scope expanded dramatically: rather than relying on brittle scrapers and fragmented external tools, why not replace Zelt and Clockify entirely?
We evolved the application from a read-only client viewer into a two-sided platform. On one side, clients manage their account, billing, and team roster. On the other, our distributed remote contractors log their daily working hours, manage timesheets, and submit leave requests. We integrated Resend for automated transactional emails and built out enterprise single sign-on with Microsoft Entra ID (currently staged for production release).
The trap of feature-first development
Taking a system from an unreleased prototype to an all-in-one company hub as a solo developer was a massive undertaking, and in the beginning, I made mistakes.
My early focus was intensely feature-driven: how quickly can I build timesheet approvals? How fast can I wire up leave tracking? But in my haste to ship raw functionality, I paid too little attention to the end-to-end user experience.
The result was that some features, while functionally “complete,” were confusing or awkward to navigate. I had built what was asked for, but not how a real client or contractor naturally expected to use it.
If I were to start that rollout over again, my approach would be inverted: start with the user’s mental model and daily workflow first, and build the minimal, polished mechanics that support those user flows seamlessly. Prioritizing UX over feature velocity might feel slower initially, but it saves countless hours of retrofitting and prevents user friction.
Solo rollouts and modern AI workflows
Rolling out a major platform solo with no dedicated QA or testing team is a trial by fire. When we launched to real clients and contractors, edge cases and bugs were naturally surfaced live in production, and I was the only developer on the hook to investigate, fix, and deploy patches.
What made that manageable was transforming my development workflow with modern AI developer tooling:
- AI-Accelerated Engineering: Leveraging tools like Claude Code and Google Antigravity allowed me to rapidly diagnose production issues, trace complex state across our React frontend and FastAPI backend, and scaffold robust fixes in minutes instead of hours.
- Guardrails and Environments: I established strict separation between staging and production environments, wired up automated CI/CD pipelines, and used agentic workflows to write regression tests and verify builds before deployment.
What building in production actually teaches
Inheriting software that other people will rely on every day strips away academic theory. It teaches you that real software engineering is rarely about writing code in a clean green field.
It is about understanding existing constraints, listening closely to where users struggle, maintaining discipline in your deployment pipelines, and having the humility to iterate when your first assumptions don’t survive contact with reality.