Turning a research archive into a decision engine
How I designed, built, and shipped a unified Customer Intelligence Platform that consolidated research, CX data, and journey intelligence across three teams. Solo, on a conference deadline, with no engineering budget.
Late 2025, UX Research became part of a newly minted Insights and Journey Management team alongside Customer Experience (CX) and Journey Management. On paper, the three functions were unified. In practice, their data lived in completely separate systems: UXR work in Dovetail, CX surveys in Qualtrics, journey artifacts in TheyDo. They had now shared access point and no way to connect signals across them.
CX ran general customer experience surveys, start- and end-of-assignment surveys, and feedback loops; all in Qualtrics, all requiring a separate login. UXR had moderated sessions, unmoderated Maze studies, synthesis and readouts in Dovetail. Journey Management was in TheyDo. A PM trying to understand the full client or provider experience had to log into three systems, know where to look in each, and piece it together themselves.
"Intelligence at the point of decision. That was the brief. Teams shouldn't have to go looking for what they need — it should be there when the conversation starts, not assembled afterward."
Getting this on an engineering roadmap would have taken quarters. We had a conference deadline and weeks to hit it. So I built it myself.
I spent time earlier in my career as a front-end developer. I know my way around a browser console and I'm comfortable getting into the code. With Claude Code available, I could move faster alone than I could waiting for an engineering ticket to get scoped and scheduled.
The platform is a Node.js/Fastify app serving static HTML, deployed to Kubernetes on AWS EKS. Five surfaces: Client Intelligence, ECS Client Intelligence, Voice of Provider, Provider CES Dashboard, and Journey Management. Each one shows the relevant data for that audience with direct links into the source systems.
The homepage shows live metrics, with a recent signals feed pulling the latest insights from Dovetail and UXR, tagged by source and date. Four intelligence modules are live. A fifth, Employee Intelligence, is already scoped, will connecting recruiter, coordinator, and ops signals to provider and client outcomes.
Getting to a running deployment took about a day of active work. The path had friction. CHG's internal platform documentation assumed an engineering audience — version mismatches between Helm and Node with no warnings during install, SSH key setup not mentioned in the onboarding guide, a missing GitHub Actions variable that caused a cryptic first deploy failure. Each one required finding the cause and either fixing it or finding the right person to escalate to.
Claude Code carried a lot of the weight. It diagnosed failures, explained infrastructure I hadn't touched in years, and filled gaps where the documentation ran out. Chrome's DevTools had AI assistance built in too, which I wasn't expecting. Debugging in the console felt different than it used to — less solo, more like thinking out loud with someone who knew the answer.
The platform was built and the deployment was live. But without authentication, it was just a URL anyone could hit. Adding Okta SSO should have been straightforward.
The technical problem: the original Okta app was a Web app type, which requires a client secret that doesn't work with browser-based JS. The fix was switching to a SPA app with Authorization Code + PKCE. That required IAM to create a new Okta application entirely.
The organizational problem: the person who had owned the relevant Okta instance had left the company. Nobody had flagged the gap. Getting IAM and the EIP platform team in the same conversation at the same time took longer than any of the technical work. I was coordinating two teams with different priorities, debugging Istio path whitelisting failures, and trying to understand Kubernetes secret provisioning — all new territory — while Claude Code helped me read the error messages.
"I was at my wit's end. The documentation had gaps, the person who knew the answer had left the company, and I couldn't get both teams in the same meeting. But that's also when it got interesting — it felt like detective work, and I've always liked detective work."
After three days it was working. The fix touched five pages (replacing the CDN-loaded Okta SDK with a locally-served file for CSP compliance), added a /login/callback page and server route, switched the OAuth flow to Authorization Code + PKCE, and required IAM to set up a new SPA Okta app with the right redirect URIs.
The platform launched at an internal conference — a couple hundred people in the room, more on the Zoom recording. The reaction was good. Not "that's interesting" but "when can I get in there."
Launching at a conference mattered. A quiet internal release would have gotten a Slack message and a few clicks. I dressed up as Steve Harvey, hosted a family feud session and the CIP was our answer machine.
The platform is live on dev.
The reaction when I describe this project is usually some version of "you did that yourself?" The assumption is that infrastructure is engineering work and research managers don't touch it. That's mostly true. It's also just a convention.
What made it possible was prior front-end experience, willingness to debug things I didn't fully understand, and AI tooling that made unfamiliar infrastructure navigable. Claude Code didn't replace engineering judgment. It made engineering judgment accessible to someone who knew the problem space but not the infrastructure stack.