diff --git a/README.md b/README.md index 3429adb..41879f5 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,33 @@ npm run dev Requires a `.env` file with `DATABASE_URL` (defaults to `file:./dev.db`). +## Environment variables + +Required in production: + +| Variable | Purpose | Notes | +|----------|---------|-------| +| `NEXT_PUBLIC_SITE_URL` | Canonical/OG/sitemap base URL | e.g. `https://buildcanada.com`. Used by `layout.tsx`, `sitemap.ts`, `robots.ts`, `lib/api/config.ts`, and JSON-LD. | +| `NEXT_PUBLIC_TRACKER_API_BASE` | Backend host for `/tracker/api/*` rewrites | Set to wherever the Outcomes Tracker API is served. Falls back to `https://www.buildcanada.com`, which will loop after cutover. | +| `YORK_FACTORY_API_URL` | York Factory CMS base URL | Defaults to `https://yorkfactory.buildcanada.com/api/v1`. Override per environment. | +| `LUMA_API_KEY` | Luma events list (`/api/events`) | Without this the homepage events list silently returns empty. | + +Recommended: + +| Variable | Purpose | +|----------|---------| +| `NEXT_PUBLIC_POSTHOG_TOKEN` | PostHog analytics + client-side exception capture (`error.tsx` boundaries report here). | +| `NEXT_PUBLIC_POSTHOG_HOST` | PostHog UI host. Defaults to `https://us.i.posthog.com`. | +| `NEXT_PUBLIC_GA_MEASUREMENT_ID` | Google Analytics. Loader is conditional — omit to disable. | +| `TRACKER_API_BASE` | Server-only override for tracker API base (read in `lib/tracker-api.ts` when no public var is set). | + +## Deployment notes + +- Set the env vars above before building. Several are baked into the static output (`NEXT_PUBLIC_*`), so a redeploy is required to change them. +- After cutover, verify `/sitemap.xml` and `/robots.txt` reference the production domain. +- Verify `/tracker` loads — if the API base is misconfigured it will silently fail to render data. +- Cloudflare-proxied projects (e.g. `/exit-tax-calculator`, `/bills`) are not served by Next; ensure their proxy rules survive any DNS / origin change. + ## Design Custom fonts: **Söhne** (headings), **Financier Text** (body), **Founders Grotesk Mono** (labels/buttons). diff --git a/instrumentation-client.ts b/instrumentation-client.ts index 043eeef..ee2e7d3 100644 --- a/instrumentation-client.ts +++ b/instrumentation-client.ts @@ -5,5 +5,6 @@ if (typeof window !== "undefined" && process.env.NEXT_PUBLIC_POSTHOG_TOKEN) { api_host: "/ph", ui_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || "https://us.i.posthog.com", defaults: "2026-01-30", + capture_exceptions: true, }); } diff --git a/src/app/about/layout.tsx b/src/app/about/layout.tsx index 162364d..bdae357 100644 --- a/src/app/about/layout.tsx +++ b/src/app/about/layout.tsx @@ -4,6 +4,7 @@ export const metadata: Metadata = { title: "About", description: "Build Canada exists to platform the bold — individuals, ideas, and reforms — that can push our country to new frontiers.", + alternates: { canonical: "/about" }, openGraph: { title: "About", description: diff --git a/src/app/builders/[slug]/page.tsx b/src/app/builders/[slug]/page.tsx index 81626a6..97edea5 100644 --- a/src/app/builders/[slug]/page.tsx +++ b/src/app/builders/[slug]/page.tsx @@ -15,6 +15,7 @@ export async function generateMetadata({ return { title: `${builder.name}: ${builder.tagline}`, description: builder.quote ?? undefined, + alternates: { canonical: `/builders/${slug}` }, openGraph: { title: `${builder.name}: ${builder.tagline} | Build Canada`, description: builder.quote ?? undefined, diff --git a/src/app/builders/opengraph-image.tsx b/src/app/builders/opengraph-image.tsx new file mode 100644 index 0000000..b6538b7 --- /dev/null +++ b/src/app/builders/opengraph-image.tsx @@ -0,0 +1,16 @@ +import { ImageResponse } from "next/og"; +import { BuildCanadaOGImage } from "@/lib/og-image-template"; + +export const size = { width: 1200, height: 630 }; +export const contentType = "image/png"; + +export default async function Image() { + return new ImageResponse( + , + { ...size }, + ); +} diff --git a/src/app/builders/page.tsx b/src/app/builders/page.tsx index 1f9b29d..61b8c53 100644 --- a/src/app/builders/page.tsx +++ b/src/app/builders/page.tsx @@ -8,6 +8,7 @@ export const metadata: Metadata = { title: "Great Canadian Builders", description: "Short stories celebrating the incredible builders who shaped Canada.", + alternates: { canonical: "/builders" }, }; export default async function BuildersPage() { diff --git a/src/app/error.tsx b/src/app/error.tsx new file mode 100644 index 0000000..8bb0e91 --- /dev/null +++ b/src/app/error.tsx @@ -0,0 +1,121 @@ +"use client"; + +import { useEffect } from "react"; +import posthog from "posthog-js"; +import { Button } from "@/components/ui/button"; + +export default function Error({ + error, + reset, +}: { + error: Error & { digest?: string }; + reset: () => void; +}) { + useEffect(() => { + if (typeof window !== "undefined" && process.env.NEXT_PUBLIC_POSTHOG_TOKEN) { + posthog.captureException(error, { + digest: error.digest, + pathname: window.location.pathname, + boundary: "app", + }); + } + }, [error]); + + return ( +
+