Add social sharing functionality to Google Antigravity with Open Graph, Twitter Cards, and share buttons.
# Social Sharing for Google Antigravity
Implement social sharing with Open Graph metadata, Twitter Cards, and share buttons.
## Dynamic Open Graph Metadata
```typescript
// app/posts/[slug]/page.tsx
import { Metadata } from "next";
import { createClient } from "@/lib/supabase/server";
interface Props {
params: { slug: string };
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const supabase = createClient();
const { data: post } = await supabase.from("posts").select("title, description, image_url").eq("slug", params.slug).single();
if (!post) return { title: "Not Found" };
const url = `https://yoursite.com/posts/${params.slug}`;
return {
title: post.title,
description: post.description,
openGraph: {
title: post.title,
description: post.description,
url,
siteName: "Your Site",
images: [{ url: post.image_url || "/og-default.png", width: 1200, height: 630 }],
type: "article",
},
twitter: {
card: "summary_large_image",
title: post.title,
description: post.description,
images: [post.image_url || "/og-default.png"],
},
};
}
export default async function PostPage({ params }: Props) {
const supabase = createClient();
const { data: post } = await supabase.from("posts").select("*").eq("slug", params.slug).single();
return (
<article>
<h1>{post.title}</h1>
<ShareButtons url={`https://yoursite.com/posts/${params.slug}`} title={post.title} />
<div>{post.content}</div>
</article>
);
}
```
## Share Buttons Component
```typescript
// components/ShareButtons.tsx
"use client";
import { useState } from "react";
interface ShareButtonsProps {
url: string;
title: string;
description?: string;
}
export function ShareButtons({ url, title, description }: ShareButtonsProps) {
const [copied, setCopied] = useState(false);
const encodedUrl = encodeURIComponent(url);
const encodedTitle = encodeURIComponent(title);
const shareLinks = {
twitter: `https://twitter.com/intent/tweet?url=${encodedUrl}&text=${encodedTitle}`,
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`,
linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`,
reddit: `https://reddit.com/submit?url=${encodedUrl}&title=${encodedTitle}`,
email: `mailto:?subject=${encodedTitle}&body=${encodedUrl}`,
};
const copyToClipboard = async () => {
await navigator.clipboard.writeText(url);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
const handleNativeShare = async () => {
if (navigator.share) {
await navigator.share({ title, text: description, url });
}
};
return (
<div className="share-buttons">
<a href={shareLinks.twitter} target="_blank" rel="noopener noreferrer" className="share-btn twitter">Twitter</a>
<a href={shareLinks.facebook} target="_blank" rel="noopener noreferrer" className="share-btn facebook">Facebook</a>
<a href={shareLinks.linkedin} target="_blank" rel="noopener noreferrer" className="share-btn linkedin">LinkedIn</a>
<a href={shareLinks.reddit} target="_blank" rel="noopener noreferrer" className="share-btn reddit">Reddit</a>
<button onClick={copyToClipboard} className="share-btn copy">{copied ? "Copied!" : "Copy Link"}</button>
{typeof navigator !== "undefined" && navigator.share && (
<button onClick={handleNativeShare} className="share-btn native">Share</button>
)}
</div>
);
}
```
## Share Count Tracking
```typescript
// app/api/share/route.ts
import { NextRequest, NextResponse } from "next/server";
import { createClient } from "@/lib/supabase/server";
export async function POST(request: NextRequest) {
const { contentType, contentId, platform } = await request.json();
const supabase = createClient();
// Track share event
await supabase.from("share_events").insert({ content_type: contentType, content_id: contentId, platform });
// Increment share count
await supabase.rpc("increment_share_count", { p_content_type: contentType, p_content_id: contentId });
return NextResponse.json({ success: true });
}
```
## Dynamic OG Image Generation
```typescript
// app/api/og/[slug]/route.tsx
import { ImageResponse } from "next/og";
import { createClient } from "@/lib/supabase/server";
export const runtime = "edge";
export async function GET(request: Request, { params }: { params: { slug: string } }) {
const supabase = createClient();
const { data: post } = await supabase.from("posts").select("title, author:profiles(full_name)").eq("slug", params.slug).single();
return new ImageResponse(
(
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", width: "100%", height: "100%", backgroundColor: "#1a1a1a", color: "#fff", padding: "40px" }}>
<div style={{ fontSize: 48, fontWeight: "bold", textAlign: "center", marginBottom: 20 }}>{post?.title || "Post"}</div>
<div style={{ fontSize: 24, color: "#888" }}>by {post?.author?.full_name || "Author"}</div>
<div style={{ fontSize: 20, color: "#666", marginTop: 40 }}>yoursite.com</div>
</div>
),
{ width: 1200, height: 630 }
);
}
```
## Share Analytics Hook
```typescript
// hooks/useShareTracking.ts
"use client";
import { useCallback } from "react";
export function useShareTracking(contentType: string, contentId: string) {
const trackShare = useCallback(async (platform: string) => {
await fetch("/api/share", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ contentType, contentId, platform }),
});
}, [contentType, contentId]);
return trackShare;
}
```
## Structured Data for Sharing
```typescript
// components/ArticleJsonLd.tsx
export function ArticleJsonLd({ post }: { post: { title: string; description: string; author: string; publishedAt: string; imageUrl: string; url: string } }) {
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
headline: post.title,
description: post.description,
author: { "@type": "Person", name: post.author },
datePublished: post.publishedAt,
image: post.imageUrl,
url: post.url,
};
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />;
}
```
## Best Practices
1. **Preview Testing**: Test OG previews with Facebook, Twitter debuggers
2. **Image Optimization**: Use proper OG image dimensions (1200x630)
3. **Fallbacks**: Provide default OG images for pages without images
4. **Tracking**: Track share events for analytics
5. **Native Share**: Use Web Share API when availableThis social prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their social implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For social projects, consider mentioning your framework version, coding style, and any specific libraries you're using.