# Social Media Post

> Social media post with author, content, media attachments, and engagement metrics.

- Name: `social-media-post`
- Categories: social
- Detail page: https://open-types.dev/types/social-media-post

## Install

```bash
# Types only
npx shadcn add @open-types/social-media-post

# Types + Zod v4 validators
npx shadcn add @open-types/social-media-post-zod

# Types + real-world examples
npx shadcn add @open-types/social-media-post-examples
```

## Types

```typescript
export type SocialMediaAttachmentType = "image" | "video" | "gif" | "link";

export interface SocialMediaAttachment {
  type: SocialMediaAttachmentType;
  url: string;
  alt?: string;
  width?: number;
  height?: number;
  thumbnail_url?: string;
}

export interface SocialMediaAuthor {
  id: string;
  username: string;
  display_name: string;
  avatar_url?: string;
  verified?: boolean;
}

export interface SocialMediaPost {
  id: string;
  author: SocialMediaAuthor;
  content: string;
  created_at: string;
  likes?: number;
  reposts?: number;
  replies?: number;
  media?: SocialMediaAttachment[];
  url?: string;
}
```

## Zod validator

```typescript
import * as z from "zod";
import type {
  SocialMediaAttachment,
  SocialMediaAttachmentType,
  SocialMediaAuthor,
  SocialMediaPost,
} from "../types/social-media-post";

export const socialMediaAttachmentTypeSchema = z.enum(["image", "video", "gif", "link"]) satisfies z.ZodType<SocialMediaAttachmentType>;

export const socialMediaAttachmentSchema = z.object({
  type: socialMediaAttachmentTypeSchema,
  url: z.url({ error: "Attachment URL must be a valid URL" }),
  alt: z.string().optional(),
  width: z.number().int({ error: "Width must be a whole number" }).min(0, {
    error: "Width cannot be negative",
  }).optional(),
  height: z.number().int({ error: "Height must be a whole number" }).min(0, {
    error: "Height cannot be negative",
  }).optional(),
  thumbnail_url: z.url({ error: "Thumbnail URL must be a valid URL" }).optional(),
}) satisfies z.ZodType<SocialMediaAttachment>;

export const socialMediaAuthorSchema = z.object({
  id: z.string().min(1, { error: "Author id is required" }),
  username: z.string().min(1, { error: "Username is required" }),
  display_name: z.string().min(1, { error: "Display name is required" }),
  avatar_url: z.url({ error: "Avatar URL must be a valid URL" }).optional(),
  verified: z.boolean().optional(),
}) satisfies z.ZodType<SocialMediaAuthor>;

export const socialMediaPostSchema = z.object({
  id: z.string().min(1, { error: "Post id is required" }),
  author: socialMediaAuthorSchema,
  content: z.string().min(1, { error: "Content is required" }),
  created_at: z.string().min(1, { error: "Created at is required" }),
  likes: z.number().int({ error: "Likes must be a whole number" }).min(0, {
    error: "Likes cannot be negative",
  }).optional(),
  reposts: z.number().int({ error: "Reposts must be a whole number" }).min(0, {
    error: "Reposts cannot be negative",
  }).optional(),
  replies: z.number().int({ error: "Replies must be a whole number" }).min(0, {
    error: "Replies cannot be negative",
  }).optional(),
  media: z.array(socialMediaAttachmentSchema).optional(),
  url: z.url({ error: "Post URL must be a valid URL" }).optional(),
}) satisfies z.ZodType<SocialMediaPost>;

export type {
  SocialMediaAttachment,
  SocialMediaAttachmentType,
  SocialMediaAuthor,
  SocialMediaPost,
} from "../types/social-media-post";
```

## Examples

```typescript
// Source: hand-crafted; modeled after Twitter/X, Bluesky, and Mastodon post shapes
import type {
  SocialMediaAttachmentType,
  SocialMediaAttachment,
  SocialMediaAuthor,
  SocialMediaPost,
} from "../types/social-media-post";

export const socialMediaAttachmentTypeExamples = {
  image: "image",
  video: "video",
  gif: "gif",
  link: "link",
} as const satisfies Record<string, SocialMediaAttachmentType>;

const imageAttachment = {
  type: "image",
  url: "https://cdn.example.com/images/photo.jpg",
  alt: "A sunset over the city skyline.",
  width: 1600,
  height: 900,
  thumbnail_url: "https://cdn.example.com/images/photo-thumb.jpg",
} as const satisfies SocialMediaAttachment;

const videoAttachment = {
  type: "video",
  url: "https://cdn.example.com/videos/demo.mp4",
  width: 1920,
  height: 1080,
  thumbnail_url: "https://cdn.example.com/videos/demo-poster.jpg",
} as const satisfies SocialMediaAttachment;

export const socialMediaAttachmentExamples = {
  image: imageAttachment,
  video: videoAttachment,
  gif: {
    type: "gif",
    url: "https://cdn.example.com/gifs/celebrate.gif",
    width: 480,
    height: 270,
  } satisfies SocialMediaAttachment,
  link: {
    type: "link",
    url: "https://open-types.dev/blog/why",
    thumbnail_url: "https://open-types.dev/og-image.png",
  } satisfies SocialMediaAttachment,
} as const;

const author = {
  id: "user_321",
  username: "open_types",
  display_name: "OpenTypes",
  avatar_url: "https://cdn.example.com/avatars/open-types.png",
  verified: true,
} as const satisfies SocialMediaAuthor;

export const socialMediaAuthorExamples = {
  verified: author,
  unverified: {
    id: "user_555",
    username: "newcomer",
    display_name: "Newcomer",
  } satisfies SocialMediaAuthor,
  noAvatar: {
    id: "user_666",
    username: "spartan",
    display_name: "Spartan",
    verified: false,
  } satisfies SocialMediaAuthor,
} as const;

const textPost = {
  id: "post_01HABCDEF0123456789ABCDE",
  author,
  content: "Excited to announce real-payload test fixtures for every schema in the registry.",
  created_at: "2026-05-16T18:30:00Z",
  likes: 482,
  reposts: 79,
  replies: 12,
  url: "https://example.com/open_types/posts/01HABCDEF",
} as const satisfies SocialMediaPost;

export const socialMediaPostExamples = {
  text: textPost,
  withImage: {
    ...textPost,
    id: "post_image_002",
    content: "Sunset photo of the day:",
    media: [imageAttachment],
  } satisfies SocialMediaPost,
  withVideo: {
    ...textPost,
    id: "post_video_003",
    content: "Watch the new release demo:",
    media: [videoAttachment],
  } satisfies SocialMediaPost,
  threadParent: {
    ...textPost,
    id: "post_thread_004",
    content: "1/ A thread about real payload testing:",
    likes: 1024,
    reposts: 320,
    replies: 88,
  } satisfies SocialMediaPost,
  minimal: {
    id: "post_min_005",
    author,
    content: "hello",
    created_at: "2026-05-16T18:30:00Z",
  } satisfies SocialMediaPost,
} as const;
```
