Case study

Case study
Product, design and engineering

CompareThat

Comparison infrastructure for Australian household finance. Bank data in, ranked and embeddable comparison tables out.

Role
Product, design and build, solo
Period
2026, ongoing
Stack
Next.js 15, TypeScript, Postgres, Drizzle, Vercel
Status
Built and deployed. Public launch gated on licensing.
01 What it is

Every rate on the page has to be the bank's number, not ours.

Most Australian comparison sites let staff type rates into a CMS. That is a compliance liability, and it is why the numbers on those sites drift from the numbers on the bank's own site.

Under the Consumer Data Right, every regulated bank publishes its product data at a public endpoint. CompareThat treats that feed as the only source of a rate, a fee or a feature, and puts editorial judgement in a second layer that can rank and annotate products but can never overwrite a published figure.

Eight consumer verticals run on it today: home loans, savings accounts, term deposits, credit cards, personal loans, car loans, superannuation and energy. Superannuation is the one that does not fit. It sits outside the Consumer Data Right, so its figures come from APRA's annual publication instead, and the surface says so on its face rather than implying a refresh it does not get.

02 The product The interface below is a demo: some components, styling and markup differ from production. This is purely a sample of production.

Try it. The menu, the filters and the table are all live.

Pick a category from the navigation to load its real column set and filter panel. Filter chips narrow the list, column headers re-sort it, and the eligibility, sponsorship and rate-movement treatments are the ones that ship.

comparethat.com.au/home-loans sample rows

Home Loans

Rates checked against every provider’s own published data on 20 Aug 2026

This is an embed to show information only, additional styling is customisable via a self-built CMS.

Shipped components and stylesheet. Product rows are illustrative. Resize the window to see the responsive card stack.

03 Live data pipeline

Four ingestion paths, one product shape.

Each source has its own schema and cadence. They normalise into a single product model, so a curated table can mix a home loan and an energy plan and the renderer does not care.

VerticalSourceShape
Home loans, savings, term deposits, credit cardsCDR banking sector, per-provider product endpointsLive JSON, refreshed per run
Personal and car loansCDR banking plus the non-bank lending sectorLive JSON, same standard
EnergyCDR energy sector, retailer plan endpoints9,162 plans at last load
SuperannuationAPRA MySuper and Choice publicationsAnnual bulk file, outside the CDR
Brands and logosPublic CDR RegisterBanking brands and logos, synced every run

Across those paths the tables carry 105 home loan lenders, 83 savings and term deposit banks, 58 card issuers, 77 personal loan and 54 car loan lenders, 37 super funds and 36 energy retailers, browsable as one directory of 202 providers.

04 Regulatory strategy

The disclosure travels with the table, not the page.

A table that can be embedded on a partner's site has to stand on its own. Before this, disclosure depended on which surface you happened to land on: the footer carried the general disclaimer, the embed carried a single line, the comparison view carried nothing.

Now one component renders under every table on every surface, and its content is category-aware, because the obligations differ. Credit with a comparison rate gets the prescribed warning plus the base criteria the figures use. Deposit products get general-advice wording instead of credit wording. Energy is neither, and says so.

Alongside it: paid listings are labelled where they appear and link to a full advertiser disclosure, eligibility restrictions surface as a badge on the product rather than in fine print, and ranking logic is written up on its own page.

Three positions sit underneath that presentation layer, and each was settled before the comparison layer was written. Together they decide what the software is permitted to do.

  • RG 234, encoded rather than reviewed for

    ASIC's Regulatory Guide 234 governs how a financial product may be promoted, and a ranked comparison table is promotion. The usual approach is a copy review before launch, which holds until someone adds a page. Here the obligations live inside the disclosure component: the category a product belongs to selects the wording, so a table carrying a comparison rate cannot render without the warning that has to travel with it. The public policy pages cite the clauses they answer to, so the reasoning is auditable rather than asserted.

  • The unlicensed-referrer model for credit

    Suggesting a particular credit product to a particular consumer, or helping them apply for it, is a licensed activity. The platform stops deliberately short of that line: it compares against published data, captures no applicant details and runs no lead forms, and an outbound click hands the consumer to the provider. That is structural rather than editorial, so there is no lead capture to switch on by accident and the position cannot drift as the product grows. It also sets the commercial model, which is referral fees on outbound clicks rather than commission on a placed loan.

  • Deposits and super sit on the other side of the line

    The referrer model covers credit and does not carry across. Deposit accounts, term deposits and superannuation are financial products, where the regulated activity is dealing or advising rather than credit assistance, and that needs an AFS licence or an authorisation under someone else's. The work has been to establish what the platform has to look like to sit inside a permitted scope, and what it would have to stop doing. That is why those surfaces are built and running against live data while the public launch stays gated. The constraint is the licensing position, not the software.

05 White-label embeds

One curated table, rendered on somebody else's domain.

A partner does not want a link out to a comparison site. They want the table on their own page, in their own colours, without maintaining any of it. So every curated table renders three ways from a single component and a single stylesheet: as a page on the site, as a chrome-less embed for a partner's page, and inside the multi-product comparison view.

The system is multi-tenant. Each tenant gets its own selection of tables, and per-tenant branding recolours the entire ramp from one accent value, so a partner is configured rather than forked. Nothing about the embed is a copy of the site, which matters when a rate changes: the partner's table updates on the same ingestion run as everything else, because it is reading the same canonical rows.

Behind it sits a bespoke CMS covering the parts an editor actually touches: long-form content, the composition of each product table, and a review workflow that gates changes before they reach a tenant. The site's own navigation is downstream of it too: a category's dropdown is built from the curated tables an editor has flagged for the menu, so renaming a table renames the menu item with no deploy. The disclosure component travels with the table into the embed, so a partner's page carries the obligations the figures create rather than inheriting whatever their own footer happens to say.

06 Search and measurement

The outbound click is the conversion, so it is the thing that gets measured.

Comparison is a search business. The architecture reflects that: a deliberate content hierarchy from vertical hub to category table to individual product, canonical URLs so the same table reachable through several routes resolves to one address, and structured data on the product and listing markup so a crawler reads the table as products with rates rather than as a grid of numbers. The listing being a genuine table rather than nested divs is part of this, not separate from it.

That hierarchy now runs past the tables: long-form guides for every vertical, a statistics section where live figures from the tables sit beside the ABS, RBA and AER benchmarks with a plain-English glossary, a directory of every provider tracked, and four calculators. Each one is built to be the page that answers the query and then hands the reader to the table that acts on it.

Measurement is built on the same constraint that shapes the compliance position. Because the platform captures no leads, there is no form completion to count, and the outbound click to a provider is the whole conversion event. GA4 and Tag Manager are set up around that: the referral out is tracked with the product, the table and the surface it came from attached, so a curated table's performance can be read per placement, and an embed on a partner domain can be told apart from the same table on the site.

That gives the two numbers the commercial model needs. Which products earn their position, and which surfaces are worth the maintenance.

07 Architecture

Two layers that never write to each other.

The split below is the whole product decision. Ingested data is read-only by construction, so no editor, and no bug in the admin, can change a published rate. Curation is a separate set of tables keyed to the same products, and the two are merged at render time.

Canonical · read-only

Written only by the ingestion run, from each provider's CDR feed and the public CDR Register.

  • Rates, comparison rates and fees
  • Eligibility and product features
  • Brand identity and logos from the Register
  • An audit row for every refresh

Curation · editor-owned

An overlay beside the canonical rows. Ranks, groups and annotates without touching a published number.

  • Curated tables with chosen columns and filters
  • Editor's picks, badges and blurbs
  • Manual rows for lenders with no CDR feed
  • Paid-placement flags that force a disclosure
Ingest path, from source feeds to a rendered comparison table Provider Consumer Data Right endpoints, the CDR Register and the APRA MySuper bulk file feed a scheduled ingest worker. The worker writes read-only canonical tables. Canonical data is merged at render time with editor-owned curation tables, producing one table that renders as a site page, a partner embed or the comparison view. Provider CDR endpoints banking and energy sectors CDR Register brands and logos APRA MySuper annual bulk file Scheduled ingest worker normalises to one product shape Canonical tables read-only, audit trail Curation tables editor-owned overlay Merged at render Site category page Partner embed Comparison view
Nothing downstream of the worker can write back to it. A rate on a partner's embed and a rate on the site are the same row, read twice.

Next.js · React · TypeScript · Postgres with Drizzle ORM · Supabase · deployed on Vercel · scheduled ingest worker

08 Notes from the build

Notes from the build.

  • The listing is a real table again

    The split-panel card look was originally nested divs, which meant no column semantics for screen readers or crawlers. It is now a genuine <table>: one <tr> per product laid out as a CSS grid, <th scope="row"> on the product name, aria-sort on the sortable column headers, and the editorial blurb folded in as a full-width third grid row inside the same bordered card. The visual result is pixel-identical to the div version.

  • Logos that survive a re-sync

    Brand logos come from the CDR Register, so every ingestion run overwrites them, including the handful of brands whose Register URL is dead. A separate override column, coalesced over the synced value, lets an editor fix a logo without the next run undoing it.

09 Why it was built

The gap was going to be spent on something.

When my role at InfoChoice ended in January, I didn't want to spend the gap refreshing job boards. So I picked the hardest thing I could usefully build, a real Australian financial product comparison platform covering home loans, savings, term deposits, credit cards, personal and car loans, superannuation and energy, and taught myself to ship it, from positioning and compliance through to schema design, deployment and production incident response.

It's the same comparison and lead generation mechanics I've worked with commercially for a decade, approached from the other side of the glass. Fourteen years of knowing what a client needs from a comparison page turned out to be a decent spec; the rest I learned by building it.

10 Where it stands

Built, deployed and running against live data. The public launch waits on licensing, not on the software.

The comparison surfaces, the admin, the ingestion and the compliance layer are complete and in production. What is deliberately unfinished is anything that would make it a referral business before the licensing position is settled.

CompareThat · case study Sample data throughout the demo