Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ const nextConfig: NextConfig = {
destination: "/builders/:slug",
permanent: true,
},
{
source: "/economic-indicators",
destination: "/prosperity-dashboard",
permanent: true,
},
{
source: "/economic-indicators/:path*",
destination: "/prosperity-dashboard/:path*",
permanent: true,
},
];
},
async rewrites() {
Expand Down
2 changes: 1 addition & 1 deletion src/app/api/economy/series/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { getEconomicSeries } from "@/lib/api/economy";
import { MEASURE_SLUGS } from "@/app/economic-indicators/indicators";
import { MEASURE_SLUGS } from "@/app/prosperity-dashboard/indicators";

// Same-origin proxy for york_factory's public series endpoint so client
// components (the canvas page) can fetch without cross-origin config. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export default function CombinedSectionChart({
return (
<div
ref={containerRef}
className="border border-border-light bg-bg p-2 [&_svg]:overflow-visible"
className="-mx-3 sm:mx-0 border border-border-light bg-bg p-2 [&_svg]:overflow-visible"
>
{grapherState ? (
<div style={{ width: size.width, height: size.height }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const CombinedSectionChart = dynamic(() => import("./CombinedSectionChart"), {
loading: () => (
// Mirrors the useChartSize clamp so deep-link hash scrolls stay accurate
// when the placeholder swaps for the real chart.
<div className="h-[clamp(338px,50vw_-_20px,478px)] animate-pulse border border-border-light bg-dark/5" />
<div className="-mx-3 sm:mx-0 h-[clamp(338px,105vw_-_41px,418px)] sm:h-[clamp(338px,50vw_-_20px,478px)] animate-pulse border border-border-light bg-dark/5" />
),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export default function IndicatorChart({
// axis and right-edge labels get clipped unless the svg can overflow.
<div
ref={containerRef}
className="border border-border-light bg-bg p-2 [&_svg]:overflow-visible"
className="-mx-3 sm:mx-0 border border-border-light bg-bg p-2 [&_svg]:overflow-visible"
>
{grapherState ? (
<div style={{ width: size.width, height: size.height }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const IndicatorChart = dynamic(() => import("./IndicatorChart"), {
loading: () => (
// Mirrors the useChartSize clamp so deep-link hash scrolls stay accurate
// when the placeholder swaps for the real chart.
<div className="h-[clamp(338px,50vw_-_20px,478px)] animate-pulse border border-border-light bg-dark/5" />
<div className="-mx-3 sm:mx-0 h-[clamp(338px,105vw_-_41px,418px)] sm:h-[clamp(338px,50vw_-_20px,478px)] animate-pulse border border-border-light bg-dark/5" />
),
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function SectionNav({ currentId }: { currentId?: string }) {
>
<div className="max-w-[1080px] mx-auto flex flex-wrap gap-x-6 gap-y-1 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden">
<Link
href="/economic-indicators"
href="/prosperity-dashboard"
aria-current={currentId === undefined ? "page" : undefined}
className={
currentId === undefined
Expand All @@ -25,7 +25,7 @@ export default function SectionNav({ currentId }: { currentId?: string }) {
return (
<Link
key={section.id}
href={`/economic-indicators/${section.id}`}
href={`/prosperity-dashboard/${section.id}`}
aria-current={isActive ? "page" : undefined}
className={
isActive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {

export const runtime = "nodejs";

export const alt = "Build Canada — Economic Indicators";
export const alt = "Build Canada — Prosperity Dashboard";

export const size = OG_SIZE;

Expand All @@ -26,7 +26,7 @@ export default async function OpengraphImage({
const { section: sectionId } = await params;
const section = SECTIONS.find((s) => s.id === sectionId);

const title = section?.title ?? "Economic Indicators";
const title = section?.title ?? "Prosperity Dashboard";
const description =
section?.description ??
"Are we moving in the right direction? Canadian prosperity, measured against the G7 and OECD.";
Expand All @@ -43,12 +43,12 @@ export default async function OpengraphImage({
const footnote = source ? `Source: ${humanizeSourceName(source.name)}` : "";

const fonts = await loadOgFonts(
`${title}${description}${chartHeading}${chart?.latestLabel ?? ""}${footnote}Economic Indicators`,
`${title}${description}${chartHeading}${chart?.latestLabel ?? ""}${footnote}Prosperity Dashboard`,
);

return new ImageResponse(
<IndicatorOgCard
label="Economic Indicators"
label="Prosperity Dashboard"
title={title}
description={description}
chartHeading={chartHeading}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ export async function generateMetadata({
const { section: sectionId } = await params;
const section = SECTIONS.find((s) => s.id === sectionId);
if (!section) return {};
const title = `${section.title} — Economic Indicators`;
const title = `${section.title} — Prosperity Dashboard`;
return {
title,
description: section.description,
alternates: { canonical: `/economic-indicators/${section.id}` },
alternates: { canonical: `/prosperity-dashboard/${section.id}` },
openGraph: {
title,
description: section.description,
Expand Down Expand Up @@ -131,7 +131,7 @@ export default async function IndicatorSectionPage({ params }: PageProps) {
const jsonLd = buildGraph(
generateOrganizationSchema(configData),
generateBreadcrumbSchema(
`/economic-indicators/${section.id}`,
`/prosperity-dashboard/${section.id}`,
section.title,
configData.siteUrl,
),
Expand Down Expand Up @@ -240,7 +240,7 @@ export default async function IndicatorSectionPage({ params }: PageProps) {
>
{prev ? (
<Link
href={`/economic-indicators/${prev.id}`}
href={`/prosperity-dashboard/${prev.id}`}
className="type-label text-dark/70 hover:text-dark underline-offset-4 hover:underline"
>
&larr; {prev.title}
Expand All @@ -250,7 +250,7 @@ export default async function IndicatorSectionPage({ params }: PageProps) {
)}
{next ? (
<Link
href={`/economic-indicators/${next.id}`}
href={`/prosperity-dashboard/${next.id}`}
className="type-label text-dark/70 hover:text-dark underline-offset-4 hover:underline text-right"
>
{next.title} &rarr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default function CanvasClient() {
const params = new URLSearchParams();
params.set("f", serializeFeeds(resolvedFeeds));
if (mode !== "indexed") params.set("mode", mode);
const next = `/economic-indicators/canvas?${params.toString()}`;
const next = `/prosperity-dashboard/canvas?${params.toString()}`;
if (`${window.location.pathname}${window.location.search}` !== next) {
window.history.replaceState(null, "", next);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export default async function OpengraphImage() {

return new ImageResponse(
<IndicatorOgCard
label="Economic Indicators"
label="Prosperity Dashboard"
title={TITLE}
description={DESCRIPTION}
chartHeading="Canada, three series overlaid"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const DESCRIPTION =
export const metadata: Metadata = {
title: "Indicator Canvas",
description: DESCRIPTION,
alternates: { canonical: "/economic-indicators/canvas" },
alternates: { canonical: "/prosperity-dashboard/canvas" },
openGraph: {
title: "Indicator Canvas",
description: DESCRIPTION,
Expand All @@ -33,10 +33,10 @@ export default function CanvasPage() {
<nav className="border-b border-border-light px-5 py-3">
<div className="max-w-[1080px] mx-auto">
<Link
href="/economic-indicators"
href="/prosperity-dashboard"
className="type-label text-dark/70 hover:text-dark underline-offset-4 hover:underline"
>
&larr; All economic indicators
&larr; Prosperity Dashboard
</Link>
</div>
</nav>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Shared catalog of the economic indicator measures served by york_factory's
// /kpis/series endpoint — each section gets its own /economic-indicators/[section]
// /kpis/series endpoint — each section gets its own /prosperity-dashboard/[section]
// page and the canvas page uses the flat list as the feed picker.

export type Indicator = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { CANADA_COLOR } from "./indicators";
import { formatValue } from "./units";

// Shared plumbing for the /economic-indicators opengraph images: one branded
// Shared plumbing for the /prosperity-dashboard opengraph images: one branded
// card layout plus builders that bake a series into a data-URI SVG. Satori
// lays out the text; the chart travels as an <img> so resvg rasterizes real
// vector paths instead of satori's partial SVG support.
Expand Down Expand Up @@ -374,7 +374,7 @@
) : null}
</div>

<img

Check warning on line 377 in src/app/prosperity-dashboard/og-card.tsx

View workflow job for this annotation

GitHub Actions / lint

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
src={chart.dataUri}
width={CHART_W}
height={CHART_H}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
export const runtime = "nodejs";

export const alt =
"Build Canada — Economic Indicators: Canadian prosperity, measured against the G7 and OECD";
"Build Canada — Prosperity Dashboard: Canadian prosperity, measured against the G7 and OECD";

export const size = OG_SIZE;

Expand All @@ -22,7 +22,7 @@ export const revalidate = 3600;
// The landing card leads with the dashboard's clearest single chart.
const FEATURED_SLUG = "gdp-per-capita-ppp";

const TITLE = "Economic Indicators";
const TITLE = "Prosperity Dashboard";
const DESCRIPTION =
"Are we moving in the right direction? Canadian prosperity, measured against the G7 and OECD.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ const DESCRIPTION =
"Are we moving in the right direction? Canada's growth, incomes, housing, safety, and wellbeing, measured against the G7 and OECD.";

export const metadata: Metadata = {
title: "Economic Indicators",
title: "Prosperity Dashboard",
description: DESCRIPTION,
alternates: { canonical: "/economic-indicators" },
alternates: { canonical: "/prosperity-dashboard" },
openGraph: {
title: "Economic Indicators",
title: "Prosperity Dashboard",
description: DESCRIPTION,
type: "website",
},
twitter: {
card: "summary_large_image",
title: "Economic Indicators",
title: "Prosperity Dashboard",
},
};

export default async function EconomicIndicatorsPage() {
export default async function ProsperityDashboardPage() {
const configData = getSiteConfig();

const featuredSeries = await Promise.all(
Expand All @@ -40,8 +40,8 @@ export default async function EconomicIndicatorsPage() {
const jsonLd = buildGraph(
generateOrganizationSchema(configData),
generateBreadcrumbSchema(
"/economic-indicators",
"Economic Indicators",
"/prosperity-dashboard",
"Prosperity Dashboard",
configData.siteUrl,
),
);
Expand All @@ -53,36 +53,14 @@ export default async function EconomicIndicatorsPage() {
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
<PageHeader
title="Economic Indicators"
description="Are we moving in the right direction? Canadian prosperity, measured."
title="Prosperity Dashboard"
/>

<SectionNav />

<section className="px-5 py-12">
<div className="max-w-[1080px] mx-auto">
<div className="mb-10 max-w-[720px] space-y-4">
<p className="type-body text-dark/80">
<strong className="text-dark">
Canada should be the most prosperous country in the world.
</strong>{" "}
The question
is whether we are turning those advantages into better lives —
and that is measurable.
</p>
<p className="type-body text-dark/80">
Prosperity is more than a growing GDP. It&rsquo;s paycheques
that buy more each year, homes people can afford, streets that
are safe, air that is clean, institutions worth trusting, and
lives people are satisfied with, confident enough in the
future to build one here. That is what these charts measure.
</p>
<p className="type-body text-dark/80">
Where the world offers a yardstick, Canada is the red line
against its G7 and OECD peers. Where the question is ours alone, how many homes we start, how fast people climb out of low income, we measure Canada against its own record. Every chart
asks the same question: are we moving in the right direction?
</p>
</div>


<div className="grid gap-5 sm:grid-cols-2">
{SECTIONS.map((section, i) => {
Expand All @@ -93,15 +71,12 @@ export default async function EconomicIndicatorsPage() {
return (
<Link
key={section.id}
href={`/economic-indicators/${section.id}`}
href={`/prosperity-dashboard/${section.id}`}
className="group flex flex-col border border-border-light p-6 hover:border-dark transition-colors"
>
<h2 className="type-h4 text-dark group-hover:underline underline-offset-4">
{section.title}
</h2>
<p className="mt-2 type-body-sm text-dark/70">
{section.description}
</p>
{preview && (
<div className="mt-5">
<p className="type-label-sm text-dark/50">
Expand All @@ -124,21 +99,6 @@ export default async function EconomicIndicatorsPage() {
);
})}

<Link
href="/economic-indicators/canvas"
className="group flex flex-col border border-border-light p-6 hover:border-dark transition-colors"
>
<h2 className="type-h4 text-dark group-hover:underline underline-offset-4">
Indicator Canvas
</h2>
<p className="mt-2 type-body-sm text-dark/70">
Overlay up to three indicator series and eyeball how they move
together.
</p>
<span className="mt-auto pt-4 type-label text-dark/70 group-hover:text-dark">
Open the canvas &rarr;
</span>
</Link>
</div>

<div className="mt-16 border-t border-border-light pt-12 text-center">
Expand All @@ -151,7 +111,7 @@ export default async function EconomicIndicatorsPage() {
— tell us and we&rsquo;ll track it.
</p>
<a
href="mailto:hi@buildcanada.com?subject=Economic%20indicators%20request"
href="mailto:hi@buildcanada.com?subject=Prosperity%20dashboard%20indicator%20request"
className="mt-6 inline-block border border-dark px-5 py-2.5 type-label text-dark hover:bg-dark hover:text-bg transition-colors"
>
Email us
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,16 @@ export function useChartSize() {
const el = containerRef.current;
if (!el) return;
const measure = () => {
const w = Math.min(1040, Math.max(320, el.clientWidth - 16));
const h = Math.max(320, Math.min(460, Math.round(w * 0.5)));
// Never exceed the container: a floor above the phone-width inner size
// (~264px on a 320px screen) would overflow and clip the right edge.
const w = Math.min(1040, Math.max(240, el.clientWidth - 16));
// Portrait-ish on phones — Grapher's line legend eats up to a third of
// the width there, so extra height keeps the plot area readable. Wide
// 2:1 on larger screens.
const h =
w < 480
? Math.max(320, Math.min(400, Math.round(w * 1.05)))
: Math.max(320, Math.min(460, Math.round(w * 0.5)));
setSize({ width: w, height: h });
};
measure();
Expand Down
8 changes: 4 additions & 4 deletions src/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type {
import { getBillsFromCivicsProject } from "@/app/bills/server/get-all-bills-from-civics-project";
import { getAllBillsFromDB } from "@/app/bills/server/get-all-bills-from-db";
import { buildAbsoluteUrl } from "@/app/bills/utils/basePath";
import { SECTIONS as ECONOMIC_SECTIONS } from "@/app/economic-indicators/indicators";
import { SECTIONS as ECONOMIC_SECTIONS } from "@/app/prosperity-dashboard/indicators";

function toValidDate(value?: Date | string): Date | undefined {
if (!value) return undefined;
Expand All @@ -24,14 +24,14 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
{ url: `${baseUrl}/memos`, lastModified: new Date(), changeFrequency: "daily", priority: 0.9 },
{ url: `${baseUrl}/posts`, lastModified: new Date(), changeFrequency: "daily", priority: 0.8 },
{ url: `${baseUrl}/projects`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.8 },
{ url: `${baseUrl}/economic-indicators`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.7 },
{ url: `${baseUrl}/prosperity-dashboard`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.7 },
...ECONOMIC_SECTIONS.map((section) => ({
url: `${baseUrl}/economic-indicators/${section.id}`,
url: `${baseUrl}/prosperity-dashboard/${section.id}`,
lastModified: new Date(),
changeFrequency: "weekly" as const,
priority: 0.6,
})),
{ url: `${baseUrl}/economic-indicators/canvas`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.5 },
{ url: `${baseUrl}/prosperity-dashboard/canvas`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.5 },
{ url: `${baseUrl}/tracker`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.8 },
{ url: `${baseUrl}/tracker/commitments`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.7 },
{ url: `${baseUrl}/tracker/faq`, lastModified: new Date(), changeFrequency: "monthly", priority: 0.4 },
Expand Down
Loading
Loading