Deploy
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
interface Profile {
|
||||
businessName: string | null
|
||||
locality: string | null
|
||||
logoUrl: string | null
|
||||
siteUrl: string | null
|
||||
}
|
||||
|
||||
async function profile(): Promise<Profile | null> {
|
||||
const base = process.env.NEXT_PUBLIC_VULA_COMMERCE_URL
|
||||
const id = process.env.NEXT_PUBLIC_VULA_PROJECT_ID
|
||||
if (!base || !id) return null
|
||||
try {
|
||||
const res = await fetch(base + '/api/public/profile/' + id, { next: { revalidate: 3600 } })
|
||||
return res.ok ? ((await res.json())?.profile ?? null) : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A title for one section of the site.
|
||||
*
|
||||
* "Services | Riverside Dental, Melville" — the section first, because
|
||||
* Google truncates the end and the section is what distinguishes this page
|
||||
* from every other page on the site. The town is included when we know it:
|
||||
* someone searching "chiropractor Richards Bay" is searching for the town as
|
||||
* much as the trade.
|
||||
*
|
||||
* Falls back to the bare section name. A title that says "Services" is worse
|
||||
* than one that says "Services | Riverside Dental" and far better than a
|
||||
* template that reads "Services | undefined".
|
||||
*/
|
||||
export async function sectionMetadata(section: string, description?: string): Promise<Metadata> {
|
||||
const p = await profile()
|
||||
const where = p?.businessName
|
||||
? p.locality
|
||||
? p.businessName + ', ' + p.locality
|
||||
: p.businessName
|
||||
: null
|
||||
|
||||
const title = where ? section + ' | ' + where : section
|
||||
|
||||
return {
|
||||
title,
|
||||
...(description ? { description } : {}),
|
||||
// The card WhatsApp, Facebook and Slack show when someone pastes the link.
|
||||
// Without og: tags they fall back to the title and description, which is why
|
||||
// a share already reads correctly — the picture is the only thing missing.
|
||||
//
|
||||
// Her own logo, or nothing. Never a stock photograph: the same one can end
|
||||
// up on several sites, and a gleaming clinic on the card with a modest room
|
||||
// at the other end is the kind of overselling this whole pass removed.
|
||||
openGraph: {
|
||||
title,
|
||||
...(description ? { description } : {}),
|
||||
...(p?.businessName ? { siteName: p.businessName } : {}),
|
||||
...(p?.siteUrl ? { url: p.siteUrl } : {}),
|
||||
type: 'website',
|
||||
locale: 'en_ZA',
|
||||
...(p?.logoUrl ? { images: [{ url: p.logoUrl }] } : {}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A page that must never appear in search results.
|
||||
*
|
||||
* A customer's own booking page is reached from a WhatsApp message with a
|
||||
* code in the link. Those links get forwarded, pasted into groups and picked
|
||||
* up, and a booking of hers turning up in Google is a breach she would hear
|
||||
* about from the patient, not from us. Checkout and account pages are the
|
||||
* same: private by purpose, not by obscurity.
|
||||
*/
|
||||
export function privatePage(section: string): Metadata {
|
||||
return {
|
||||
title: section,
|
||||
robots: { index: false, follow: false },
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user