Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { texts } from '@/texts'
|
|
|
|
/**
|
|
* Shared helpers for Phase 3 SEO landing pages' `generateMetadata` /
|
|
* JSON-LD. Centralizes the site origin so every landing page (hub,
|
|
* category, city, combo, event) builds canonical URLs and `JsonLd`
|
|
* absolute URLs the same way instead of each redeclaring its own
|
|
* `SITE_URL` constant.
|
|
*/
|
|
|
|
function resolveSiteUrl(raw = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://backoffice.ghabilee.ir') {
|
|
const url = new URL(raw)
|
|
|
|
return url.toString().replace(/\/+$/, '')
|
|
}
|
|
|
|
export const SITE_URL = resolveSiteUrl()
|
|
|
|
/**
|
|
* Backoffice must never be indexed, regardless of SITE_URL.
|
|
*/
|
|
export function isSearchEngineIndexable(_siteUrl = SITE_URL): boolean {
|
|
return false
|
|
}
|
|
|
|
export const DEFAULT_OG_IMAGE_PATH = '/og-default.jpg'
|
|
|
|
/** Absolute canonical URL for a site-relative path (e.g. `/city/tehran`). */
|
|
export function buildCanonicalUrl(path: string): string {
|
|
return `${SITE_URL}${path.startsWith('/') ? path : `/${path}`}`
|
|
}
|
|
|
|
/**
|
|
* OG image priority per docs/workflows/fa/seo-landing-pages.md § تصویر OG:
|
|
* category `og_image_url` → `cover_image_url` → `banner_image_url` →
|
|
* event poster → site default. Caller passes candidates in that order;
|
|
* the first non-empty one wins.
|
|
*/
|
|
export function resolveOgImage(...candidates: (string | null | undefined)[]): string {
|
|
const match = candidates.find((candidate) => !!candidate)
|
|
|
|
return match ?? buildCanonicalUrl(DEFAULT_OG_IMAGE_PATH)
|
|
}
|
|
|
|
export const DEFAULT_SEO_DESCRIPTION = texts.seo.discoveryDescription
|