In about 300 hours — business analysis, planning, and training included — we built one of the largest lake management companies in the nation a complete data and application layer on top of its existing business systems:
- A Microsoft Fabric lakehouse fed by Fivetran — including three custom connectors we wrote for systems Fivetran doesn’t support.
- A custom analytics portal with 77 purpose-built dashboards and tools behind the company’s Microsoft Entra sign-in.
- A Claude-powered Ask AI assistant that answers from the same vetted numbers the dashboards show.
- Shop-floor TV displays, and a native iPad app for field applicators that writes to the same database as its web twin.
- All of the infrastructure underneath, set up from zero: the company had no GitHub, no CI, no test suite, and no Azure footprint — cloud accounts to Claude access arrived as part of the same 300 hours.
- Training for the client’s existing non-technical employees to create dashboards themselves, by describing what they need to Claude — and an architecture that makes that safe: a dashboard is one folder with one manifest, in a repo that can’t touch sign-in or data access, checked by CI before it ships. They went on to build roughly half of the 77.
The warehouse was live and the first dashboard in daily use two weeks in. One deployable container, continuous deployment from GitHub, built with Claude Code as the pair programmer. This is what it looks like in practice — and why the same pattern applies well beyond lake management.
- Client
- One of the largest lake management companies in the nation — PE-owned, 30+ branches nationwide, multi-brand, built largely through a roll-up strategy
- Effort
- About 300 hours, end to end — business analysis, planning, build, and training · first dashboard in daily use two weeks in
- Data platform
- Microsoft Fabric lakehouse · Fivetran + 3 custom connectors · 102 tables across 6 schemas
- Application
- One FastAPI portal, one container on Azure App Service · 77 dashboards & tools in 12 categories
- AI layer
- Claude-powered Ask AI · 51 manifest-declared tools · answers only from vetted dashboard numbers
- Security
- Entra tenant at the front door · category gates mapped to Entra groups · branch/region data scoping
- Surfaces
- Browser portal · read-only TV display lane · native iPad field app with a web twin
- Infrastructure
- Set up from zero — Azure accounts, GitHub org, CI/CD, unit tests, Claude for the team · none existed before
- Training
- Client non-developers — branch managers included — taught to build dashboards by describing them to Claude · part of the 300 hours, not an add-on
- Delivery
- About 140,000 lines across three repos · 662 merged PRs · CI on every change · the client's trained team built roughly half the dashboards with Claude
The starting point
The client is a large, private-equity-owned operator with 30+ branches around the nation, put together largely through a roll-up strategy, plus several acquired brands — among them a fish hatchery business, a fountain-and-aeration service shop in Texas, a fisheries operation, and a Midwest lake-and-pond services company. The branches operate largely independently — their own local processes, their own habits, often their own tools — and roll-ups compound in systems as fast as they compound in revenue: every acquisition arrives with its own way of doing things, so the same job — invoicing, dispatch, payroll, call tracking — is done with different processes, in different systems, from one branch to the next. By the time we arrived, the answers lived everywhere: NetSuite for the ERP, Aspire for field operations, Paycor for payroll, 3CX for phones, CallRail for marketing calls, Service Fusion running the fountain shop, Shopify for the web store. The N-systems problem, in the wild.
The reporting reality matched:
- The monthly operating report — an Excel workbook assembled by hand.
- The fountain shop’s team scorecard — a Power BI model.
- Pesticide compliance records — a legacy PHP tool.
- The phone team’s daily call report — a hand-kept workbook.
Each one worked — and each one was a silo with a person attached.
That is exactly the situation a centralized data warehouse exists for. We ingested every system’s data into one warehouse, normalized it — so “revenue,” “customer,” and “job” mean the same thing from every branch and brand — and exposed a clean set of tables that all reporting runs on. For a PE-owned roll-up that pays twice: reporting — board packs, branch-to-branch comparisons, consolidated financials — reads from a single source of truth instead of N exports, and Ask AI gets one vetted place to answer from. We’ve written about why roll-up data challenges are multiplicative; this engagement is that playbook, executed.
And there was no engineering foundation to inherit. Before this engagement the company had no GitHub, no CI, no test suite, no Azure footprint, and no AI tooling — none of the infrastructure the rest of this case study takes for granted. Setting it up was part of the work, not a prerequisite for it: we created the Azure accounts and resources, the GitHub organization and repositories, the CI pipelines and unit tests, and Claude access for the team. The developer stack arrived with the platform.
The architecture, in five decisions
1. One warehouse, no exceptions. A Microsoft Fabric lakehouse is the single source every tool reads. Fivetran loads NetSuite natively; for Aspire, Paycor, and 3CX — systems Fivetran has no connector for — we wrote custom connectors with the Fivetran Connector SDK. The 3CX connector reads the API’s own metadata and syncs every entity it exposes, so new entities appear without code changes. Each source lands raw and is normalized into clean, consistently defined tables — so reporting across 30+ independently run branches reads one vocabulary, not seven systems’ worth. Today the dashboards read 102 distinct warehouse tables across six schemas, every query filtered for deleted rows and stamped with sync freshness.
2. Drop a folder, get a dashboard. The portal is one FastAPI application in one container on Azure App Service, but the dashboards live in their own repo — one folder each, with a single manifest.toml. As the platform’s own documentation puts it: “Adding a dashboard = drop a folder containing a dashboard/manifest.toml. The platform discovers it from that file and wires up everything” — the URL, the portal tile, the AI tools, and the access gate. Seventy-seven dashboards were added without ever editing the host.
- Every dashboard ships with a mock-data mode, a region/branch scope bar, Excel export, and a methodology note.
- The two-repo split is deliberate: the portal repo — sign-in, data access, the AI, the display lane — is not editable by non-coders, while the implementation repo that hosts the dashboards asks only that a folder be filled in correctly.
- That boundary is what let us train client employees who aren’t developers — branch managers included — to build dashboards themselves: they describe the dashboard they need to Claude, Claude writes the folder, and the manifest contract means the platform wires up everything else.
- CI validates every manifest and compiles every change before merge, and nothing in the implementation repo can touch sign-in, data access, or the AI layer — so a non-developer with Claude is a safe contributor, not a risk.
3. An AI that can’t make numbers up. Ask AI — the portal’s Claude-powered assistant — answers only through tools that call the dashboards’ own vetted endpoints, filtered by the same permissions as everything else, so its numbers are exactly the dashboards’ numbers. It matters enough to this story that it gets its own section below.
4. Rent the front door, own the permissions. We didn’t write our own security for the portal’s front door — Microsoft’s already exists. The portal sits behind Microsoft Entra, so before any of our code runs you have to be an account in the company’s own tenant; passwords, MFA, and sessions are Microsoft’s problem, not a hand-rolled sign-in layer waiting to be breached. Who-sees-what — the only part that’s actually specific to the business — is where the custom security code went:
- Each of the portal’s twelve categories maps to a Microsoft Entra security group — a dashboard’s category is its gate.
- An Access Control dashboard assigns each person’s data scope on top, which every dashboard reads before it renders a number.
- The same gates drive the AI’s tool filtering and the display lane’s read-only allowlist.
5. The same data from the boardroom to the shop floor to the pond. One warehouse serves three very different audiences:
- The boardroom and the branches — managers use the portal with per-user scoping: a branch manager sees their branch; regional managers see everything.
- The shop floor — the fountain shop runs dispatch boards and the team scorecard on wall TVs through a read-only display lane. Signage players can’t sign in, so the lane serves exactly the endpoints the manifest allows and nothing else.
- The pond — field applicators record Department of Agriculture pesticide treatments on a native iPad app whose web twin lives in the portal. Both write to the same tables through the same API, so there is no copy and nothing to sync. It replaced the legacy PHP tool, with invoicing moved into NetSuite.
Ask AI: the assistant that can’t make numbers up
Ask AI is a Claude tool-calling assistant wired into the portal, and it exists to answer the question every operator actually has: just tell me the number. What makes it trustworthy is what it is not allowed to do. From the design docs: “The assistant never invents numbers. Every figure comes from a tool, and each tool calls one of the existing (already-vetted) dashboard endpoints in-process, so the AI’s numbers are exactly the dashboard’s numbers.”
How a question becomes an answer:
- Anyone with portal access asks in plain English — a branch’s revenue this month, how the fountain shop’s scorecard is trending, which calls the phone team is losing.
- Claude picks from the 51 tools declared across the dashboards’ manifests — and only from the ones that user is allowed to open.
- The tool calls the same vetted endpoint the dashboard renders from, in-process.
- The answer comes back in seconds, carrying the dashboard’s number — not a model’s recollection of it.
The trust rule: the AI is a faster way to the dashboards’ numbers — never a second opinion on them. That one constraint is the answer to the problem that kills most “chat with your data” demos: the first hallucinated figure in a board meeting is the last time anyone opens the chat.
The guardrails:
- Same permissions as the portal. Tools are filtered per request by the same access gate — a tool whose dashboard you can’t open is never even offered to the model. Ask AI is a convenience layer over the permission system, never a way around it.
- Scoped like the screen. Branch and region scoping applies to the AI’s answers exactly as it does to the dashboards.
- SQL on a leash. Read-only, single statement, row-capped — and payroll tables blocked by default.
- The power tool is gated. A separate, admin-only AI Analyst opens the whole warehouse to guarded ad-hoc questions, with charts and Excel exports.
And the assistant compounds with the platform. Because tools are declared in each dashboard’s manifest, every new dashboard — including the ones the client’s own non-developers build with Claude — teaches Ask AI a new tool the moment it merges, access gate included, with no AI work done by anyone. The 51 tools it has today grew out of the catalog; the next dashboard makes it 52.
Under the hood
Two data paths, deliberately separate. Reads and writes don’t share a store:
- Analytical reads go to the Fabric lakehouse through one shared data-access module — ODBC, a service principal, no per-dashboard connection code. The warehouse’s six schemas map one-to-one to the source systems, so lineage stays legible.
- Operational data the tools create themselves — pipelines, scorecards, safety and compliance records, settings — lives in an Azure SQL application database instead, which is why September’s document-store-to-relational cutovers never had to touch the warehouse.
- A Data Source Management console watches the seam: live connector status, a 30-day sync timeline, warnings, and one-click syncs.
What every dashboard inherits. A shared platform library hands each folder:
- Warehouse access, Excel export, usage tracking, notifications with @mentions, a people directory, and a document store.
- Email — sent through Microsoft Graph as the App Service’s managed identity, so there is no mailbox password stored anywhere.
- One brand-kit CSS and JS file, served by the platform and referenced by URL — the reason 77 tools built by different hands, engineers and trained non-developers alike, look and behave like one product.
The ship pipeline. From pull request to production:
- Every pull request validates manifests and compiles the code before it can merge.
- A merge triggers the platform to build a fresh container image tagged with the commit SHA, point the web app at it, and restart — GitHub authenticating to Azure with OIDC, not a stored secret.
- Observability was built in from the start: logs flow to Application Insights, a System Logs dashboard surfaces errors, stack traces, and slow requests with request-id lookup across every tool, and a Usage Analytics dashboard shows who opens what — adoption measured, not assumed.
What 300 hours produced
The portal spans twelve categories. Among them:
- Operations — the Weekly Regional Report; Branch MOR, which replaced the monthly Excel workbook with a live NetSuite view of revenue, costs, and branch profit; Field Ops Command over Aspire.
- Finance — NetSuite-style financial statements with drill-downs, A/P aging, and utilization from Aspire hours against Paycor paid hours.
- Sales & marketing — call tracking, renewal tracking, and territory mapping drawn over live revenue.
- The fountain shop’s suite — dispatch, job queue, and the wall scorecard, rebuilt from the Power BI model “with its scoring decisions kept.”
- Compliance — safety task tracking with escalating reminders; the Department of Agriculture record system.
- Field tools that would be products in their own right — a sonar mapper that turns a Lowrance recording into 2D and rotatable 3D lake maps entirely in the browser, a dredging transect analyzer, pond design tools, and report generators that price line items from NetSuite.
Who built the 77 is half the story. We built roughly half of them. The other half were built by the client’s own employees — the people we trained, describing the dashboard they needed to Claude in the implementation repo. The catalog reflects that:
- Some dashboards were built by one person, for exactly that person’s job — a daily workflow tool with a single user.
- Others, especially in finance and operations, are company-wide surfaces — the Branch MOR, the financial statements, and the Weekly Regional Report are read across every branch and region.
The platform makes both ends economical. A single-user tool is worth building when it’s one folder and an afternoon with Claude, and a company-wide dashboard ships through the same CI checks, access gates, and brand kit as everything else — so both look and behave like one product.
Two categories deserve a special mention for anyone reading this from the investment world:
- Acquisition Pipeline — a drag-and-drop M&A pipeline with financials, calls, and contacts over a map of branches, targets, and 23,000+ industry businesses.
- Integration Status — a per-acquisition planner tracking how far each acquired company is onto the shared systems.
The company is a buy-and-build operator; this is deal sourcing and post-close integration tooling built on the company’s own warehouse — the pattern we’ve described for PE firms, running inside a portfolio-scale operating company.
The cutting edge: AI beyond the dashboards
The same engagement also reached places that used to require specialist teams and specialist software — because AI collapsed the cost of trying:
- 3D modelling of bodies of water. The sonar mapper turns a Lowrance sonar recording into 2D and rotatable 3D lake models, entirely in the browser — bathymetry that used to mean dedicated desktop software, shipped as one more portal tool.
- Finding the next customer’s pond. AI-driven analysis of geographic data identifies bodies of water across the United States — turning the company’s addressable market into a working dataset: every pond and lake a candidate for outreach, not a dot on someone’s mental map.
- Routes that feed the marketing engine. AI draws and optimizes routes, and the results feed straight into the marketing engine — so outreach concentrates along the geography the business actually drives, instead of scattering spend across the map.
The training: turning portal users into dashboard builders
The single most consequential deliverable of the engagement wasn’t a dashboard — it was the training that taught the client’s own non-technical employees to create and ship dashboards of their own with AI. It was scoped into the 300 hours from the start, not bolted on as a handoff at the end:
- Who we trained. Client employees who aren’t developers — branch managers included — working in the same implementation repo as our engineers from the start.
- What they learned. The full describe-build-ship loop: describe the dashboard you need to Claude, let it write the folder against the manifest contract, open the pull request, and let CI validate the manifest and compile the change before it merges.
- Why it’s safe to teach. The implementation repo can’t touch sign-in, data access, or the AI layer — so a trainee’s worst day is a failed CI check, never a broken platform.
- What it produced. The team we trained built roughly half of the 77 dashboards — and because every merge adds patterns and examples that Claude draws on, the training keeps appreciating after we leave.
Why let non-developers build the dashboards?
Because the oldest failure mode in business software is translation. The person who understands the business describes what they need to an engineer; the engineer interprets; weeks later a dashboard comes back that is almost — but not quite — what was meant, and the loop starts again. Every handoff loses fidelity, and the person with the knowledge is reduced to writing requirements about the thing instead of making the thing.
A portal like this, with Claude doing the coding, inverts that loop:
- The business expert takes the first stab. A branch manager who knows exactly which numbers run their morning doesn’t describe a dashboard — they build the first version of it, by telling Claude what they need. The requirements are expressed in the product itself.
- Engineers clean up instead of starting over. When a dashboard needs hardening — a faster query, an edge case, a sturdier layout — an engineer steps into working software that already encodes the business intent, rather than interpreting a spec document. Review beats requirements-gathering.
- The platform keeps the floor safe. The manifest contract, CI, and the access gates mean the first stab can’t break sign-in, data access, or anyone else’s numbers — which is precisely what makes handing non-developers the keys responsible rather than reckless.
The inversion: the people with the business knowledge stop describing the product and start building its first version. The spec and the prototype become the same artifact — and the engineer’s job shifts from translation to polish.
And it compounds. Every merged dashboard adds another worked example, another pattern, another shared component to the repo — and Claude works from that repo and its instruction files on every build. The more the codebase contains, the better Claude gets at building in it, and the more the non-technical builders can do without help: things that needed an engineer in month one are a describe-it-to-Claude job by month six. The repo doesn’t just accumulate functionality — it accumulates skills, and every contributor, technical or not, inherits all of them on their next build.
Two engineering stories
When the source API broke. In September, Aspire’s API began refusing full-width queries over about 60 seconds on its largest tables, taking the nightly sync down. The fix lived in the connector, not the warehouse: fetch columns in splits, isolate errors per table, drive child records from their parents, run one backfill. Deployed four days later. The 3CX connector got the inverse treatment in October — when the Daily Call Report’s year-ago comparison hit the start of the connector’s history, we backfilled a year of phone data by walking the connector’s checkpoint back through Fivetran’s state API.
From JSON documents to real tables, without downtime. The write-back tools (the M&A pipeline, SPIFF, safety records) started life on a document store and were moved to typed relational tables in September — each cutover runs itself at startup in one transaction, fences the old store, and can be rolled back with an admin call rather than a redeploy. Along the way a whole class of bug was closed platform-wide: reads now fail closed rather than ever silently overwriting real data with defaults. Internal tools, treated like production software — because the moment people run their day on them, that’s what they are.
How it went this fast
From first commit to the portal running the company’s operating rhythm took about 300 hours of our time, start to finish — and that is not 300 hours of pure engineering: the figure includes the business analysis and planning that decided what to build, the developer infrastructure stood up from nothing — Azure accounts, the GitHub organization, CI, the test suite, Claude for the team — and the training that put the client’s own non-developers in a position to extend it. The start set the pace: the warehouse was up and the first dashboard in real daily use within two weeks, with the first fifteen dashboards landed by day eight. The busiest month saw 211 commits.
Three things compounded:
- The manifest contract made each dashboard a small, same-shaped unit — small enough to build, review, and test as a piece.
- Claude Code was the pair programmer throughout, with our engineers directing, reviewing, and testing every change — across the repos, 677 + 134 + 22 commits and 662 merged pull requests, with 119 test files and CI validating every manifest and compiling every change before merge.
- Co-development with the client’s own team — their staff committed to the same repos from the start, and we trained employees who aren’t developers to build dashboards of their own by describing them to Claude in the implementation repo. The platform isn’t just maintainable by the people who own it, it’s extendable by them: by the end, roughly half of the 77 dashboards were theirs.
The result deploys as one container with continuous deployment from GitHub — a merge builds the image, points the web app at it, and restarts.
The transferable pattern: one warehouse under everything; a portal that writes, not just reads; an AI constrained to the vetted numbers; and a per-tool contract small enough that AI-assisted development — and the client’s own non-developers — can ship daily without breaking what’s live. None of this is lake-management-specific — it’s what AI-enabling an operating company actually looks like.
What’s next
The platform changed what the company believes is possible, and the engagement has entered its next phase: we are now embarking on replacing their operational software with custom software, built on the same foundation. The architecture was designed for exactly this. The warehouse abstracts the source systems, so as each vendor tool gives way to purpose-built software writing to the same tables, the dashboards, Ask AI, and the reporting rhythm keep running without a skipped beat — the iPad field app already proved the pattern when it replaced the legacy compliance tool outright. Step by step, the portal stops being a layer on top of the business systems and becomes the business system.