diff --git a/src/MyWebLog.Domain/SupportTypes.fs b/src/MyWebLog.Domain/SupportTypes.fs
index e947d65..775c916 100644
--- a/src/MyWebLog.Domain/SupportTypes.fs
+++ b/src/MyWebLog.Domain/SupportTypes.fs
@@ -382,6 +382,171 @@ type Revision = {
{ AsOf = Noda.epoch; Text = Html "" }
+/// Properties for an OpenGraph audio file
+[]
+type OpenGraphAudio = {
+ /// The URL for this audio file
+ Url: string
+
+ /// The URL for this audio file for sites that require https
+ SecureUrl: string option
+
+ /// The MIME type of the audio file
+ Type: string option
+} with
+
+ /// An empty audio file
+ static member Empty =
+ { Url = ""
+ SecureUrl = None
+ Type = None }
+
+
+/// Properties for an OpenGraph image
+[]
+type OpenGraphImage = {
+ /// The URL for this image
+ Url: string
+
+ /// The URL for this image for sites that require https
+ SecureUrl: string option
+
+ /// The MIME type of the image
+ Type: string option
+
+ /// The image width (in pixels)
+ Width: int option
+
+ /// The image height (in pixels)
+ Height: int option
+
+ /// Alternative text for the image
+ Alt: string option
+} with
+
+ /// An empty image file
+ static member Empty =
+ { Url = ""
+ SecureUrl = None
+ Type = None
+ Width = None
+ Height = None
+ Alt = None }
+
+
+/// Properties for an OpenGraph video
+[]
+type OpenGraphVideo = {
+ /// The URL for this video
+ Url: string
+
+ /// The URL for this video for sites that require https
+ SecureUrl: string option
+
+ /// The MIME type of the video
+ Type: string option
+
+ /// The video width (in pixels)
+ Width: int option
+
+ /// The video height (in pixels)
+ Height: int option
+} with
+
+ /// An empty video file
+ static member Empty =
+ { Url = ""
+ SecureUrl = None
+ Type = None
+ Width = None
+ Height = None }
+
+
+/// Valid og:type values
+[]
+type OpenGraphType =
+ | Article
+ | Book
+ | MusicAlbum
+ | MusicPlaylist
+ | MusicRadioStation
+ | MusicSong
+ | PaymentLink
+ | Profile
+ | VideoEpisode
+ | VideoMovie
+ | VideoOther
+ | VideoTvShow
+ | Website
+
+ /// Parse a string into an OpenGraph type
+ /// The string to be parsed
+ /// The OpenGraphType parsed from the string
+ /// If the string is not valid
+ static member Parse typ =
+ match typ with
+ | "article" -> Article
+ | "book" -> Book
+ | "music.album" -> MusicAlbum
+ | "music.playlist" -> MusicPlaylist
+ | "music.radio_station" -> MusicRadioStation
+ | "music.song" -> MusicSong
+ | "payment.link" -> PaymentLink
+ | "profile" -> Profile
+ | "video.episode" -> VideoEpisode
+ | "video.movie" -> VideoMovie
+ | "video.other" -> VideoOther
+ | "video.tv_show" -> VideoTvShow
+ | "website" -> Website
+ | _ -> invalidArg (nameof typ) $"{typ} is not a valid OpenGraph type"
+
+ override this.ToString() =
+ match this with
+ | Article -> "article"
+ | Book -> "book"
+ | MusicAlbum -> "music.album"
+ | MusicPlaylist -> "music.playlist"
+ | MusicRadioStation -> "music.radio_station"
+ | MusicSong -> "music.song"
+ | PaymentLink -> "payment.link"
+ | Profile -> "profile"
+ | VideoEpisode -> "video.episode"
+ | VideoMovie -> "video.movie"
+ | VideoOther -> "video.other"
+ | VideoTvShow -> "video.tv_show"
+ | Website -> "website"
+
+
+/// Top-level properties for OpenGraph
+[]
+type OpenGraphTopLevel = {
+
+ /// The type of object represented
+ Type: OpenGraphType
+
+ /// An image representing the object
+ Image: OpenGraphImage
+
+ /// An audio file associated with the object
+ Audio: OpenGraphAudio option
+
+ /// A short description of the object
+ Description: string option
+
+ /// The article (a, an, the, etc.) which should be used to refer to this object
+ Determiner: string option
+
+ /// The primary locale of the content of the object
+ Locale: string option
+
+ /// Other locales in which the content of the object is available
+ LocaleAlternate: string list option
+
+ /// A video file assigned with the object
+ Video: OpenGraphVideo option
+}
+
+
/// A permanent link
[]
type Permalink =