NNabeel Hassan

Blog · July 29, 2026 · 8 min read

Building a GraphQL Admin Dashboard for Amazon Sellers: A Fractional CTO's Playbook

By Nabeel HassanAI Engineer · ICPC World Finalist

TL;DR: At Bettershop Consulting I give CTO-level guidance on a complex React, TypeScript and GraphQL web app that puts an admin dashboard and analytics in front of Amazon sellers. That sounds like plumbing until you realize a seller makes real money decisions off the numbers on that screen, so the whole job is making a data-heavy dashboard that is fast, honest and never quietly wrong. This is what building analytics software for people who act on it taught me: why GraphQL earns its place here, why the hard part is the data model and not the charts, and how the same discipline shows up in the AI agents I ship now.

Most dashboard projects are judged on how they look in a screenshot. This one is judged on whether a seller who reprices a product, kills an ad campaign or reorders stock because of a number on the screen made a good call. That is a different bar. A pretty chart that is subtly stale or double-counts a return is worse than no chart, because it launders a bad number into a confident decision. Amazon selling is a margins game, and margins are unforgiving of software that rounds the truth.

What an Amazon seller actually needs from a dashboard

Amazon gives sellers a firehose of data across a spread of surfaces: orders, returns, fees, advertising, inventory, settlements. The raw material is all there and almost none of it is decision-ready. A seller does not want another table of rows. They want the two or three numbers that tell them what to do this week: which products are actually profitable after every fee, which ad spend is buying real orders, and what is about to stock out.

So the product is not a viewer, it is an opinion. The dashboard's job is to take a mess of source data and turn it into a small number of trustworthy answers. That framing decides everything downstream. It means most of the engineering is not in the front end at all. It is in the layer that ingests, reconciles and models the data so that by the time a chart renders, the hard thinking is already done.

This is the same lesson I keep relearning across very different products. A voice agent is only half the build, and the CRM and dashboard behind it are the other half. An Amazon seller dashboard is the same shape: the chart is the visible ten percent, and the data pipeline nobody sees is the ninety percent that decides whether it can be trusted.

Why GraphQL is the right fit here

The instinct to reach for GraphQL can be cargo-culting, but for a dashboard like this it earns its keep for a concrete reason: the shape of what the client needs varies wildly by screen, and the underlying data is deeply relational.

A profitability view needs products joined to orders joined to fees joined to returns. An advertising view needs campaigns joined to keywords joined to attributed sales. An inventory view needs stock joined to velocity joined to inbound shipments. With a pile of REST endpoints you either over-fetch, dragging entire objects across the wire to use one field, or you sprout a new bespoke endpoint for every screen until the API is a graveyard of one-off routes. GraphQL lets each screen ask for exactly the graph it needs in one round trip, and the type system doubles as a contract the TypeScript front end can trust.

The part that matters more than the query language, though, is the discipline it forces. A GraphQL schema makes you name your domain precisely. What is a product? What is an order line versus an order? What exactly is profit, and which fees are inside it? Writing that schema is really writing down the business, and getting it right is most of the battle. A sloppy schema produces a sloppy dashboard no matter how nice the React looks on top of it.

One definition of profit, everywhere

The single most important rule on this project is that a number means the same thing on every screen. Profit on the overview card, profit in the product detail view and profit in an exported report have to be the identical calculation, not three implementations that drift apart the first time someone adds a fee type.

That is the exact instinct I wrote about leading a sports-tech platform at RAQTS: share the truth, never the platform. A leaderboard position is one authoritative object rendered on three screens, and a seller's margin is one authoritative calculation surfaced in a dozen places. The moment two views disagree about a number, the seller stops trusting all of them, and a dashboard nobody trusts is worse than no dashboard because it still costs money to run.

The hard parts hide in the data, not the UI

Charts are the easy part. The work that actually decides whether this product is any good lives underneath, in the unglamorous reconciliation nobody demos.

None of that shows up in a screenshot, and all of it decides whether the dashboard is trustworthy. As a fractional CTO the most valuable thing I do here is not writing a component, it is insisting that these ledger-level questions get answered precisely before anyone argues about chart colors.

Making a data-heavy front end feel fast

Once the data is honest, the front end still has to feel instant, because a seller checking numbers between other tasks will not wait on a spinner. A React and TypeScript dashboard over a relational GraphQL backend has a few predictable performance traps, and handling them is most of the front-end craft.

The big one is the classic N+1 query hiding behind a clean-looking GraphQL request. A query that asks for a hundred products and each product's fees can quietly become a hundred and one database trips if the resolvers are naive, so batching and careful resolver design at the data layer is what keeps a rich screen from becoming a slow one. The client side has its own version of the same discipline: cache aggressively, fetch the shape a screen needs rather than everything, and never block the whole view on the one expensive widget.

The honesty rule carries into the UI too. A dashboard should never show a confident number while it is still loading or partially failed. If one data source is lagging, the right move is to say so on that tile rather than render a plausible-looking zero, the same way I build AR overlays and voice agents that signal uncertainty instead of faking confidence. A blank that admits "still loading" is safer than a number that looks final and is not.

What a fractional CTO actually adds on a project like this

Bettershop already had a capable team and a real product. Stepping in as a fractional CTO on something like that is not about being the person who writes the most code, it is about being the person who protects the few decisions that are expensive to get wrong. On a seller analytics app those decisions are almost all about data integrity: the definition of profit, how returns and fees are handled, where the single source of truth lives, and what the app is allowed to show when it is unsure.

That is the same judgement I bring in from every other engagement, whether it was stepping in mid-build at a sports-tech company or leading clinical XR where a wrong number has real stakes. The tools differ, the discipline does not: find what the product cannot afford to get wrong and build the boundary around that first.

What building analytics for real decisions taught me

An Amazon seller dashboard is a small, sharp version of a lesson that applies to almost any data product I have shipped, an arc from Unity and SDKs into web and AI that I traced in my freelance lessons piece.

Software people act on has to be honest before it is beautiful, and honest is harder. That is the whole job on a seller analytics dashboard, and it is exactly the standard I hold the AI systems I build to now.


I lead engineering as a fractional CTO and build data-heavy web products and AI systems, from React and GraphQL dashboards to voice and chat agents, for teams that need the hard parts done right. If that is you, more about my background here, or book a call.

FAQ

Why use GraphQL for an analytics dashboard?

Because a dashboard's data is deeply relational and the shape each screen needs varies wildly, which is exactly what GraphQL handles well. A profitability view joins products to orders to fees to returns; an advertising view joins campaigns to keywords to attributed sales; an inventory view joins stock to velocity to inbound shipments. With REST you either over-fetch whole objects to use one field or sprout a bespoke endpoint per screen until the API is a graveyard of one-off routes. GraphQL lets each screen request exactly the graph it needs in one round trip, and the schema doubles as a typed contract the TypeScript front end can trust. The deeper value is the discipline it forces: writing the schema means naming your domain precisely (what is a product, an order line, profit, which fees are inside it), and getting that right is most of the battle.

What is the hardest part of building an Amazon seller dashboard?

The data model, not the UI. Charts are easy; the work that decides whether the product is trustworthy is the reconciliation underneath. Amazon's fee structure is layered and changing, so a profit number that ignores a referral, FBA, storage or return-processing fee can tell a seller a losing product is a winner. Returns arrive weeks after the sale, so revenue has to be treated as provisional until the return window resolves. Sellers across multiple marketplaces have data in different currencies and fee regimes that must roll into one comparable view without silently mixing units, and time-zone boundaries quietly shift every daily figure if you pick the wrong midnight. None of that shows up in a screenshot, and all of it decides whether a seller who acts on the number made a good call.

What does a fractional CTO add to a data dashboard project?

Protection of the few decisions that are expensive to get wrong, which on an analytics app are almost all about data integrity: the single definition of profit used everywhere, how returns and fees are modeled, where the source of truth lives, and what the app is allowed to show when it is unsure. On a team that already writes good code, the CTO's value is not the most components shipped, it is insisting these ledger-level questions get answered precisely before anyone argues about chart colors. The same rule holds across projects: a number has to mean the same thing on every screen, computed once, or the dashboard loses trust, and a dashboard nobody trusts is worse than none because it still costs money to run.

Building something in this space?

I take on AI-agent, automation and product work directly — scoped fast, shipped fast.

Book a discovery call →

Keep reading