From 2f0b657fa6e675a337ff33cd187a968330881d9e Mon Sep 17 00:00:00 2001 From: Yuhao <16722967+clementinelove@users.noreply.github.com> Date: Sat, 9 Nov 2024 19:56:07 +0000 Subject: [PATCH 1/2] Expose metadata via Metadata variable - expose `Metadata` typed variable to next to have it auto-gen metadata tags --- src/app/about/page.tsx | 14 +++- src/app/blog/[slug]/page.tsx | 68 ++++++++++++++++--- src/app/blog/page.tsx | 7 +- src/app/blog/utils.ts | 2 + src/app/causes/page.tsx | 7 +- src/app/charity-partnership/page.tsx | 8 ++- src/app/collaborations/page.tsx | 7 +- src/app/faq/page.tsx | 7 +- src/app/get-in-touch/page.tsx | 7 +- src/app/info/cookie-policy/page.tsx | 7 +- src/app/info/privacy-notice/page.tsx | 7 +- .../terms-and-conditions-for-users/page.tsx | 7 +- src/app/layout.tsx | 9 +++ src/app/page.tsx | 8 ++- src/app/press/page.tsx | 6 +- 15 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index d02b5c0..03f1bf7 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -11,6 +11,19 @@ import LoudspeakerIcon from "@/assets/graphics/loudspeaker_icon.webp"; import LightbulbIcon from "@/assets/graphics/lightbulb_icon.webp"; import Image from "next/image"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | About Us", + openGraph: { + images: [ + { + url: Elgars.src, + alt: "Picture of the founders – siblings James and Lizzie Elgar", + }, + ], + } +} const icons = [ { @@ -36,7 +49,6 @@ const icons = [ const About = (): JSX.Element => { return ( <> - now-u | About Us
; +} + +export async function generateMetadata( + { params }: MetadataProps, + parent: ResolvingMetadata, +): Promise { + const slug = (await params).slug; + const blog = await getPostBySlug(slug); + + if (blog !== undefined) { + const author = blog.author?.full_name; + const headerImage = blog.headerImage; + + return { + title: `${blog.title} - now-u Blog`, + description: blog.subtitle, + authors: author !== undefined ? [{ name: author }] : [], + openGraph: { + type: "article", + images: [ + { + url: headerImage, + }, + ], + locale: "en_GB", + publishedTime: blog.publishedDate, + modifiedTime: blog.updateDate, + expirationTime: blog.archiveDate, + }, + }; + } else { + return { + title: "Unknown Blog Post", + }; + } +} + function AuthorTile(props: { name: string; description: string; @@ -50,12 +93,11 @@ export default async function Page({ if (blog === undefined) { notFound(); } - const archiveDate: number = Date.parse(blog.archiveDate ?? "") + const archiveDate: number = Date.parse(blog.archiveDate ?? ""); const blogIsArchived = isNaN(archiveDate) ? false : Date.now() > archiveDate; return ( <> - {`now-u | ${blog.title}`}
@@ -65,13 +107,19 @@ export default async function Page({ {/* Archived Warning Banner */} - { blogIsArchived && -
- -

The article you are looking at is archived and possibly outdated!

-
- } - + {blogIsArchived && ( +
+ +

+ The article you are looking at is archived and possibly + outdated! +

+
+ )} +
{ const remotePosts = await getBlogPosts(); @@ -23,8 +28,6 @@ async function Blog(): Promise { return ( <> - now-u | Blog -
{ headerImage: blog.header_image.url, readingTime: blog.reading_time.toString(), publishedDate: blog.release_at, + updateDate: blog.updated_at, archiveDate: blog.end_at ?? undefined } } else { diff --git a/src/app/causes/page.tsx b/src/app/causes/page.tsx index c3a1ecd..621e47b 100644 --- a/src/app/causes/page.tsx +++ b/src/app/causes/page.tsx @@ -4,6 +4,11 @@ import { Header } from "@/components/Header"; import { Newsletter } from "@/components/Newsletter"; import Image from "next/image"; import { type Cause, getCauses } from "@/services/api"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | Causes" +} const CauseTile = (props: { cause: Cause }): JSX.Element => { const { header_image: headerImage, title } = props.cause; @@ -34,8 +39,6 @@ export default async function CausesPage(): Promise { return ( <> - now-u | Causes -
- now-u | Charity Partnership
=> { @@ -9,8 +14,6 @@ const PartnersPage = async (): Promise => { return ( <> - now-u | Collaborations -
diff --git a/src/app/faq/page.tsx b/src/app/faq/page.tsx index a52f7bc..48ab44c 100644 --- a/src/app/faq/page.tsx +++ b/src/app/faq/page.tsx @@ -3,6 +3,11 @@ import Link from "next/link"; import { Header } from "@/components/Header"; import { getFaqs } from "@/services/api"; import { FAQBlock } from "@/app/faq/FAQBlock"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | FAQs" +} async function FAQPage(): Promise { @@ -10,8 +15,6 @@ async function FAQPage(): Promise { return ( <> - now-u | FAQs -

diff --git a/src/app/get-in-touch/page.tsx b/src/app/get-in-touch/page.tsx index 74e154d..acbd0b8 100644 --- a/src/app/get-in-touch/page.tsx +++ b/src/app/get-in-touch/page.tsx @@ -9,6 +9,11 @@ import { import { Header } from "@/components/Header"; import { ContactTile } from "./ContactTile"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | Get In Touch" +} const contacts = [ { @@ -36,8 +41,6 @@ const contacts = [ const GetInTouch = (): JSX.Element => { return ( <> - now-u | Get In Touch -

diff --git a/src/app/info/cookie-policy/page.tsx b/src/app/info/cookie-policy/page.tsx index c377660..278d564 100644 --- a/src/app/info/cookie-policy/page.tsx +++ b/src/app/info/cookie-policy/page.tsx @@ -1,6 +1,11 @@ import React from "react"; import fs from "fs"; import md from "markdown-it"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | Cookie Policy" +} export default async function Page(): Promise { const cookiePolicyFile = fs.readFileSync( @@ -10,8 +15,6 @@ export default async function Page(): Promise { return ( <> - {`now-u | Cookie Policy`} -

Cookie Policy

{ const privacyNoticeFile = fs.readFileSync( @@ -10,8 +15,6 @@ export default async function Page(): Promise { return ( <> - {`now-u | Privacy Notice`} -

Privacy Notice

{ const termsFile = fs.readFileSync( @@ -10,8 +15,6 @@ export default async function Page(): Promise { return ( <> - {`now-u | Terms and Conditions for Users`} -
await import("@/components/Analytics")); @@ -40,6 +41,14 @@ const ppPangram = localFont({ variable: '--font-pppangram' }) +export const metadata: Metadata = { + title: "now-u", + openGraph: { + siteName: "now-u", + type: "website" + } +} + interface RootLayoutProps { children: React.ReactNode; } diff --git a/src/app/page.tsx b/src/app/page.tsx index e98a8c5..18c17e0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -13,6 +13,12 @@ import GlobeIcon from "@/assets/graphics/globe_icon.webp"; import Image from "next/image"; import { AppStoreBadge, PlayStoreBadge } from "@/components/AppStoreBadge"; import { Newsletter } from "@/components/Newsletter"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | Home" +} + const icons = [ { @@ -38,8 +44,6 @@ const icons = [ function Home(): JSX.Element { return ( <> - now-u | Home -
diff --git a/src/app/press/page.tsx b/src/app/press/page.tsx index cc46156..48c425a 100644 --- a/src/app/press/page.tsx +++ b/src/app/press/page.tsx @@ -6,6 +6,11 @@ import Image from "next/image"; import Link from "next/link"; import { PRESS_EMAIL } from "@/utils/constants"; import { type PressArticle, pressArticles } from "./pressArticles"; +import type { Metadata } from "next"; + +export const metadata: Metadata = { + title: "now-u | Press" +} interface PressPack { title: string; @@ -95,7 +100,6 @@ export default async function Press(): Promise { return ( <> - now-u | Press
From c700b087db672da924944ff32f28a03391825db0 Mon Sep 17 00:00:00 2001 From: Yuhao <16722967+clementinelove@users.noreply.github.com> Date: Sun, 10 Nov 2024 10:56:43 +0000 Subject: [PATCH 2/2] Satisfy linter; Add default og:image; Update all title to 'xxx | now-u' from 'now-u | xxx' 'xxx | now-u' is going to provide user better UX vs 'now-u | xxx' because it's easier for user to tell the current path of the page from a compact browser tab title. --- .eslintrc.cjs | 1 + src/app/blog/page.tsx | 4 ++-- src/app/causes/page.tsx | 2 +- src/app/charity-partnership/page.tsx | 2 +- src/app/collaborations/page.tsx | 2 +- src/app/faq/page.tsx | 2 +- src/app/get-in-touch/page.tsx | 2 +- src/app/info/cookie-policy/page.tsx | 2 +- src/app/info/privacy-notice/page.tsx | 2 +- .../terms-and-conditions-for-users/page.tsx | 2 +- src/app/layout.tsx | 10 +++++++++- src/app/page.tsx | 2 +- src/app/press/page.tsx | 2 +- src/assets/graphics/og-image.png | Bin 0 -> 17060 bytes 14 files changed, 22 insertions(+), 13 deletions(-) create mode 100644 src/assets/graphics/og-image.png diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 7163b0d..53129b6 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -32,6 +32,7 @@ module.exports = { }, ], "@typescript-eslint/naming-convention": 1, + "@typescript-eslint/strict-boolean-expressions": "warn" }, settings: { react: { version: "18.2.0" }, diff --git a/src/app/blog/page.tsx b/src/app/blog/page.tsx index 7db86f7..95cb221 100644 --- a/src/app/blog/page.tsx +++ b/src/app/blog/page.tsx @@ -4,10 +4,10 @@ import { Header } from "@/components/Header"; import { BlogTile, type BlogTileProps } from "@/components/BlogTile"; import { Newsletter } from "@/components/Newsletter"; import { getBlogPosts } from "@/services/api"; -import { Metadata } from "next"; +import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Blog" + title: "Blog | now-u" } async function Blog(): Promise { diff --git a/src/app/causes/page.tsx b/src/app/causes/page.tsx index 621e47b..4edd1c9 100644 --- a/src/app/causes/page.tsx +++ b/src/app/causes/page.tsx @@ -7,7 +7,7 @@ import { type Cause, getCauses } from "@/services/api"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Causes" + title: "Causes | now-u" } const CauseTile = (props: { cause: Cause }): JSX.Element => { diff --git a/src/app/charity-partnership/page.tsx b/src/app/charity-partnership/page.tsx index 4c685df..df900fb 100644 --- a/src/app/charity-partnership/page.tsx +++ b/src/app/charity-partnership/page.tsx @@ -11,7 +11,7 @@ import { LinkButton } from "@/components/Button"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Charity Partnership" + title: "Charity Partnership | now-u" } diff --git a/src/app/collaborations/page.tsx b/src/app/collaborations/page.tsx index 13d7f95..37b6ae2 100644 --- a/src/app/collaborations/page.tsx +++ b/src/app/collaborations/page.tsx @@ -5,7 +5,7 @@ import { getOrganisations } from "@/services/api"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Collaborations" + title: "Collaborations | now-u" } const PartnersPage = async (): Promise => { diff --git a/src/app/faq/page.tsx b/src/app/faq/page.tsx index 48ab44c..10e2704 100644 --- a/src/app/faq/page.tsx +++ b/src/app/faq/page.tsx @@ -6,7 +6,7 @@ import { FAQBlock } from "@/app/faq/FAQBlock"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | FAQs" + title: "FAQs | now-u" } diff --git a/src/app/get-in-touch/page.tsx b/src/app/get-in-touch/page.tsx index acbd0b8..24bccbb 100644 --- a/src/app/get-in-touch/page.tsx +++ b/src/app/get-in-touch/page.tsx @@ -12,7 +12,7 @@ import { ContactTile } from "./ContactTile"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Get In Touch" + title: "Get In Touch | now-u" } const contacts = [ diff --git a/src/app/info/cookie-policy/page.tsx b/src/app/info/cookie-policy/page.tsx index 278d564..cc1df08 100644 --- a/src/app/info/cookie-policy/page.tsx +++ b/src/app/info/cookie-policy/page.tsx @@ -4,7 +4,7 @@ import md from "markdown-it"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Cookie Policy" + title: "Cookie Policy | now-u" } export default async function Page(): Promise { diff --git a/src/app/info/privacy-notice/page.tsx b/src/app/info/privacy-notice/page.tsx index 0e6844e..20836c4 100644 --- a/src/app/info/privacy-notice/page.tsx +++ b/src/app/info/privacy-notice/page.tsx @@ -4,7 +4,7 @@ import md from "markdown-it"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Privacy Notice" + title: "Privacy Notice | now-u" } export default async function Page(): Promise { diff --git a/src/app/info/terms-and-conditions-for-users/page.tsx b/src/app/info/terms-and-conditions-for-users/page.tsx index 494ba40..56f4ebc 100644 --- a/src/app/info/terms-and-conditions-for-users/page.tsx +++ b/src/app/info/terms-and-conditions-for-users/page.tsx @@ -4,7 +4,7 @@ import md from "markdown-it"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Terms and Conditions for Users" + title: "Terms and Conditions for Users | now-u" } export default async function Page(): Promise { diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 798c3bf..cdbee11 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -7,7 +7,8 @@ import { Footer } from "@/components/Footer"; import { getRequiredEnvironmentVariable } from "@/utils/getRequiredEnvironmentVariable"; import { Toaster } from "@/components/ui/toaster"; import { ScrollHack } from "@/components/ScrollHack"; -import { Metadata } from "next"; +import OGImage from "assets/graphics/og-image.png" +import type { Metadata } from "next"; const Analytics = lazy(async () => await import("@/components/Analytics")); @@ -42,9 +43,16 @@ const ppPangram = localFont({ }) export const metadata: Metadata = { + metadataBase: new URL('https://www.now-u.com'), title: "now-u", + description: "Learn more about this non-profit with a mission to inform, involve and inspire people to help tackle some of the world's most pressing social and environmental issues.", openGraph: { siteName: "now-u", + images: [ + { + url: OGImage.src, + } + ], type: "website" } } diff --git a/src/app/page.tsx b/src/app/page.tsx index 18c17e0..74fce5a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -16,7 +16,7 @@ import { Newsletter } from "@/components/Newsletter"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Home" + title: "Drive Changes | now-u" } diff --git a/src/app/press/page.tsx b/src/app/press/page.tsx index 48c425a..51f8d9c 100644 --- a/src/app/press/page.tsx +++ b/src/app/press/page.tsx @@ -9,7 +9,7 @@ import { type PressArticle, pressArticles } from "./pressArticles"; import type { Metadata } from "next"; export const metadata: Metadata = { - title: "now-u | Press" + title: "Press | now-u" } interface PressPack { diff --git a/src/assets/graphics/og-image.png b/src/assets/graphics/og-image.png new file mode 100644 index 0000000000000000000000000000000000000000..820c19dec958ceee9ecc6128579758a8f968290e GIT binary patch literal 17060 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 KRMBr&@BI&{{j;?I literal 0 HcmV?d00001