Skip to content

Instantly share code, notes, and snippets.

@xinha-sh
Created January 3, 2024 08:30
Show Gist options
  • Select an option

  • Save xinha-sh/726521ade24472605974621d5f2b409d to your computer and use it in GitHub Desktop.

Select an option

Save xinha-sh/726521ade24472605974621d5f2b409d to your computer and use it in GitHub Desktop.
Typescript schema for html meta including open-graph, twitter and o-embed
import { z } from "zod"
const metadataSchema = z.object({
title: z.string().optional(),
description: z.string().optional(),
keywords: z.array(z.string()).optional(),
favicon: z.string().optional(),
author: z.string().optional(),
themeColor: z.string().optional(),
canonicalUrl: z.string().optional(),
oEmbed: z
.object({
type: z.union([
z.literal("photo"),
z.literal("video"),
z.literal("link"),
z.literal("rich"),
]),
version: z.string().optional(),
title: z.string().optional(),
authorName: z.string().optional(),
authorUrl: z.string().optional(),
providerName: z.string().optional(),
providerUrl: z.string().optional(),
cacheAge: z.number().optional(),
thumbnails: z
.tuple([
z.object({
url: z.string().optional(),
width: z.number().optional(),
height: z.number().optional(),
}),
])
.optional(),
})
.optional(),
twitter: z
.object({
card: z.string(),
site: z.string().optional(),
creator: z.string().optional(),
creatorId: z.string().optional(),
title: z.string().optional(),
description: z.string().optional(),
players: z
.array(
z.object({
url: z.string(),
stream: z.string().optional(),
height: z.number().optional(),
width: z.number().optional(),
})
)
.optional(),
apps: z.object({
iphone: z.object({
id: z.string(),
name: z.string(),
url: z.string(),
}),
ipad: z.object({
id: z.string(),
name: z.string(),
url: z.string(),
}),
googleplay: z.object({
id: z.string(),
name: z.string(),
url: z.string(),
}),
}),
images: z.array(
z.object({
url: z.string(),
alt: z.string(),
})
),
})
.optional(),
openGraph: z
.object({
title: z.string(),
type: z.string(),
images: z
.array(
z.object({
url: z.string(),
secure_url: z.string().optional(),
type: z.string(),
width: z.number(),
height: z.number(),
alt: z.string().optional(),
})
)
.optional(),
url: z.string().optional(),
audio: z
.array(
z.object({
url: z.string(),
secure_url: z.string().optional(),
type: z.string(),
})
)
.optional(),
description: z.string().optional(),
determiner: z.string().optional(),
site_name: z.string().optional(),
locale: z.string(),
localeAlt: z.string(),
videos: z.array(
z.object({
url: z.string(),
stream: z.string().optional(),
height: z.number().optional(),
width: z.number().optional(),
tags: z.array(z.string()).optional(),
})
),
article: z.object({
publishedTime: z.string().optional(),
modifiedTime: z.string().optional(),
expirationTime: z.string().optional(),
author: z.string().optional(),
section: z.string().optional(),
tags: z.array(z.string()).optional(),
}),
})
.optional(),
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment