Skip to content

feat: add per-suburb editorial narrative paragraph - #165

Merged
fatblaine merged 1 commit into
devfrom
feat/adsense
Aug 6, 2026
Merged

fatblaine merged 1 commit into
devfrom
feat/adsense

Conversation

@fatblaine

@fatblaine fatblaine commented Aug 6, 2026 •

Copy link
Copy Markdown
Owner

What

A data-driven editorial paragraph on every suburb card (adsense-plan §8.5.1). Pure frontend — no backend, schema, or data change.

  • New framework-free buildNarrative() (src/lib/narrative.ts) assembles up to three paragraphs from the suburb's own ABS data:
    1. rented-share change 2011→2021 (verb varies by magnitude) plus the Residency Shift Index, labelled a "SuburbLens custom heuristic";
    2. community mix — overseas-born share (100 − Australia%), top origin, top non-English languages;
    3. university-qualified share vs the city-cohort benchmark, plus recorded crime for Melbourne suburbs only.
  • New SuburbNarrative component renders it as an "In brief" card, mounted in SuburbCard between the Shift Index and Nearby sections.

Why

The most important AdSense content-hardening step: turn each "charts + numbers" page into one with human-readable prose so it reads as genuine content, not scaled/templated filler — the strongest defence against a Low value content rejection. The text is rule-based, not LLM-generated (LLM bulk-generation would itself look like scaled-content abuse); each paragraph's value comes from that suburb's unique real data. Anti-template guard (§8.5.7): verbs and framing switch on numeric bands, so suburbs read differently rather than swapping only the place name.

Two deliberate design points:

  • Zero extra requests — SuburbNarrative reuses the five hooks SuburbCard already calls, sharing the TanStack cache; paragraphs fill in progressively as each query settles.
  • Never fabricated — crime is Greater Melbourne only; where it 404s (Sydney) the sentence is omitted, not invented. buildNarrative is kept React-free so the pending prerender-body tier (§8.5.6 step 7) can reuse the exact same logic.

How to test

  • cd frontend && npx tsc --noEmit — passes clean.
  • npm run dev, open a Melbourne suburb (e.g. via search) — the "In brief" card shows three paragraphs including a crime sentence, ending with a Source: ABS Census 2021 (TSP), SA2 "…". Crime: Victoria Crime Statistics Agency. line.
  • Open a Sydney suburb — same card, but the crime sentence is absent and the source line omits the crime attribution.
  • Confirm the Network tab shows no additional requests beyond those the card's chart sections already make.
  • A suburb missing a dimension (e.g. no education data) simply drops that sentence — the card still renders.

Summary by CodeRabbit

  • New Features
    • Added suburb narratives to suburb cards, providing plain-language insights on tenure, community, education, and crime.
    • Narratives adapt to available data and include relevant source attribution.
    • Added support for highlighting percentage changes and demographic differences with clear, banded wording.

Turn each suburb's "charts + numbers" page into one with human-readable
prose, so the page reads as original content rather than templated filler
(adsense-plan §8.5.1).

A framework-free buildNarrative() assembles up to three paragraphs from
the suburb's real ABS data: the rented-share trend plus the Residency
Shift Index, the community mix (overseas-born share, top origin, top
non-English languages), and the university-qualified share vs the city
benchmark (with crime for Melbourne suburbs only, never fabricated where
it 404s). Verbs and framing switch on numeric bands so suburbs read
differently, not just with the place name swapped.

SuburbNarrative reuses the five hooks SuburbCard already calls, so it
shares the TanStack cache and fires no extra network requests.
@fatblaine
fatblaine requested a lite review from Copilot August 6, 2026 04:55
@fatblaine fatblaine self-assigned this Aug 6, 2026
@fatblaine fatblaine added documentation Improvements or additions to documentation enhancement New feature or request labels Aug 6, 2026
@fatblaine
fatblaine merged commit c287ac9 into dev Aug 6, 2026
4 of 5 checks passed
@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3670fed0-261d-4084-a4b1-d5aa014e6aa5

📥 Commits

Reviewing files that changed from the base of the PR and between 342a4da and 3db7158.

📒 Files selected for processing (3)
  • frontend/src/components/SuburbCard.tsx
  • frontend/src/components/SuburbNarrative.tsx
  • frontend/src/lib/narrative.ts

📝 Walkthrough

Walkthrough

Changes

Suburb narrative

Layer / File(s) Summary
Narrative contracts and paragraph generation
frontend/src/lib/narrative.ts
Defines narrative inputs and outputs, formatting helpers, tenure wording, and tenure paragraphs.
Community, education, and crime assembly
frontend/src/lib/narrative.ts
Generates community, education, and optional crime paragraphs, then assembles paragraphs and source attribution.
Suburb-card rendering
frontend/src/components/SuburbNarrative.tsx, frontend/src/components/SuburbCard.tsx
Loads suburb data, builds the narrative, and renders available paragraphs with source attribution.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SuburbCard
  participant SuburbNarrative
  participant buildNarrative
  SuburbCard->>SuburbNarrative: pass salCode
  SuburbNarrative->>buildNarrative: pass suburb data responses
  buildNarrative-->>SuburbNarrative: return paragraphs and sources
  SuburbNarrative-->>SuburbCard: render narrative section
Loading

Suggested reviewers: copilot

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/adsense

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a data-driven “In brief” editorial narrative to each suburb card by generating prose from existing suburb data queries, aiming to improve human-readable content density (AdSense hardening) without backend/schema changes.

Changes:

  • Introduces a framework-free buildNarrative() generator that assembles up to three narrative paragraphs plus a source line from ABS/crime datasets.
  • Adds a new SuburbNarrative React component that renders the narrative card and progressively fills content as existing queries resolve.
  • Mounts the narrative card into SuburbCard between the Shift Index and Nearby sections.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
frontend/src/lib/narrative.ts Implements narrative text generation from tenure/language/birth/education/crime inputs and emits paragraphs + source attribution.
frontend/src/components/SuburbNarrative.tsx New UI component that calls the existing suburb hooks and renders the “In brief” prose card.
frontend/src/components/SuburbCard.tsx Inserts SuburbNarrative into the suburb card layout.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +167 to +169
const source =
`Source: ABS Census 2021 (TSP), SA2 “${tenure.sa2Name}”.` +
(crime?.periods?.length ? ' Crime: Victoria Crime Statistics Agency.' : '')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants