diff --git a/frontend/src/components/partials/PostCard.tsx b/frontend/src/components/partials/PostCard.tsx
new file mode 100644
index 0000000..15d57cd
--- /dev/null
+++ b/frontend/src/components/partials/PostCard.tsx
@@ -0,0 +1,174 @@
+import { Link } from "react-router-dom"
+import { Card } from "@/components/ui/card"
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
+import { File, FileText, Play, ImagePlay } from "lucide-react"
+import { relativeTime, getFirstGrapheme } from "@/lib/utils"
+
+import { getFileUrl } from "@/services/api"
+
+interface PostCardProps {
+ post_id: string
+ title: string
+ description: string
+ creator: {
+ [key: string]: string
+ }
+ date: {
+ [key: string]: string
+ }
+ media: Array<{
+ [key: string]: string
+ }>
+ media_count: number
+ source_site: {
+ [key: string]: string
+ }
+}
+
+export function PostCard({ post_id, title, description, creator, date, media, media_count, source_site }: PostCardProps) {
+ const renderMedia = () => {
+ const mediaCount = media.length;
+
+ const baseImageClass = "object-cover w-full h-full rounded-md";
+
+ if (mediaCount === 0) {
+ return (
+
+ );
+ }
+
+ if (mediaCount === 1) {
+ return (
+
+

+ {renderMediaBadge(media[0])}
+
+ );
+ }
+
+ if (mediaCount === 2) {
+ return (
+
+ {media.map((item, index) => (
+
+

+ {renderMediaBadge(item)}
+
+ ))}
+
+ );
+ }
+
+ if (mediaCount === 3) {
+ return (
+
+
+

+ {renderMediaBadge(media[0])}
+
+
+

+ {renderMediaBadge(media[1])}
+
+
+

+ {renderMediaBadge(media[2])}
+
+
+ );
+ }
+
+ return (
+
+ {media.slice(0, 4).map((item, index) => (
+
+

+ {renderMediaBadge(item)}
+ {index === 3 && mediaCount > 4 && (
+
+ +{mediaCount - 4}
+
+ )}
+
+ ))}
+
+ );
+ };
+
+ const renderMediaBadge = (item: { type: 'image' | 'video' | 'gif' | 'pdf', src: string }) => {
+ if (item.type === 'video') {
+ return (
+
+ );
+ } else if (item.type === 'gif') {
+ return (
+
+
+ GIF
+
+ );
+ } else if (item.type === 'pdf') {
+ return (
+
+
+ Doc
+
+ );
+ };
+ return null;
+ };
+
+ const renderSourceSiteIcon = () => {
+ if (source_site.slug === 'twitter') {
+ return (
+
+

+
+ )
+ } else if (source_site.slug === 'furaffinity') {
+ return (
+
+

+
+ )
+ }
+ }
+
+ return (
+
+
+
+ {renderMedia()}
+ {renderSourceSiteIcon()}
+
+
+ {title || (description.length > 28 ? `${description.substring(0, 28)}...` : description)}
+
+
+
+
+ {creator.avatar && }
+ {getFirstGrapheme(creator.name)}
+
+
{creator.name}
+
+
+
{relativeTime(date.created)}
+
+
+
+
+
+
+
+ )
+}
+