# How to Add Social Media Integration to Your App (Copy-Paste Prompts Included)

- Tool: App Features
- Last updated: July 2026

## TL;DR

Social media integration has three distinct jobs: social login (Sign in with Google or Facebook), share buttons (post a link to Twitter/X or LinkedIn), and account connection (store OAuth tokens to read or post on the user's behalf). Lovable handles social login in under an hour via Supabase Auth. Share buttons take another hour. Account connection with token storage adds a full day. Total: 6–12 hours with AI tools, $0–25/month.

## What Social Media Integration Actually Covers

Social media integration is not one feature — it's a family of three. Social login lets users authenticate with an existing Google, GitHub, or Facebook account instead of creating a password. Share buttons let users broadcast any piece of content to their social feeds with one click, using the Web Share API on mobile or platform-specific share URLs on desktop. Account connection goes further: the user grants your app permission to read their posts, follower count, or profile, or to post on their behalf — and you store the OAuth token to do so server-side. Most apps start with social login, add share buttons a sprint later, and only tackle account connection when a core feature explicitly requires it. The product decisions that matter: which platforms to support (each one is a separate OAuth flow to maintain), what permission scopes to request (ask for the minimum), and how to handle token expiry without breaking user sessions.

## Anatomy of the Feature

Six components. Social login and share buttons are straightforward; account connection and Open Graph tags are where first builds stall.

- **Social login** (backend): Supabase Auth OAuth providers (Google, GitHub, Facebook, Apple) configured in the Supabase Dashboard under Authentication → Providers. In Lovable, the same toggle lives in the Cloud tab → Users & Auth. Each provider requires an OAuth app in that platform's developer console with the Supabase callback URL registered.
- **Share button** (ui): Web Share API (navigator.share) for mobile native sheet — triggers the OS-level share dialog with the URL, title, and text pre-filled. Falls back to platform-specific share URLs on desktop: twitter.com/intent/tweet, linkedin.com/sharing/shareArticle, facebook.com/sharer/sharer.php. Rendered as a shadcn/ui DropdownMenu listing available platforms.
- **OAuth account connection** (backend): Authorization code flow separate from login OAuth. User clicks 'Connect Twitter account', is redirected to the platform's OAuth page, grants permissions, and the platform redirects back to a Supabase Edge Function callback that exchanges the code for access_token and refresh_token. Tokens are stored encrypted in a user_social_connections table.
- **Open Graph meta tags** (ui): HTML meta tags (og:title, og:description, og:image, og:url) that social platforms read when generating preview cards. In V0/Next.js, set via generateMetadata() in each page's page.tsx. In Lovable/Vite, set via react-helmet or a document.head manipulation in the layout component.
- **Social data pull** (backend): Platform API calls to fetch the user's posts, follower count, or profile data — made server-side only via a Supabase Edge Function using the stored OAuth token. Results cached in Supabase to stay within platform rate limits. Never call platform APIs from the client — tokens must stay server-side.
- **Social feed embed** (ui): Third-party embed scripts (Twitter/X embed, LinkedIn Share Plugin, Facebook SDK) loaded lazily after the main page is interactive. Each script adds 80–200KB to the page. Use Intersection Observer to load only when the component scrolls into view.

## Data model

One table stores connected social accounts per user with encrypted tokens and revocation support. Run this in the Supabase SQL editor:

```sql
create table public.user_social_connections (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users(id) on delete cascade not null,
  platform text not null,
  platform_user_id text not null,
  username text,
  access_token text not null,
  refresh_token text,
  scope text[],
  expires_at timestamptz,
  connected_at timestamptz not null default now(),
  revoked_at timestamptz,
  constraint uq_user_platform unique (user_id, platform)
);

alter table public.user_social_connections enable row level security;

create policy "Users can view own connections"
  on public.user_social_connections for select
  using (auth.uid() = user_id);

create policy "Users can insert own connections"
  on public.user_social_connections for insert
  with check (auth.uid() = user_id);

create policy "Users can update own connections"
  on public.user_social_connections for update
  using (auth.uid() = user_id);

create policy "Users can delete own connections"
  on public.user_social_connections for delete
  using (auth.uid() = user_id);

create index user_social_connections_user_idx
  on public.user_social_connections (user_id, platform)
  where revoked_at is null;
```

The unique constraint on (user_id, platform) prevents duplicate connections. The partial index on non-revoked rows keeps the 'connected accounts' query fast. Store access_token and refresh_token values encrypted at rest — in production, use Supabase Vault or encrypt before insert using pgcrypto's pgp_sym_encrypt with a key from your Supabase secrets.

## Build paths

### Lovable — fit 4/10, 6–10 hours

Social login via Supabase Auth is turnkey in Lovable's Cloud tab — one toggle per provider. Share buttons generate cleanly from the prompt. Account connection OAuth needs an Edge Function for the callback and manual redirect URI registration on each platform's developer console.

1. Open the Cloud tab in Lovable and go to Users & Auth — enable Google, GitHub, and any other social login providers by toggling them on and pasting in the client ID and secret from each platform's developer console
2. Register the Supabase callback URL shown in the Cloud tab as the authorized redirect URI in each platform's OAuth settings — copy it exactly, including the trailing path
3. Paste the prompt below and let Agent Mode build the share button component, the user_social_connections table and RLS, the Edge Function OAuth callback, and the connected accounts settings page
4. Click Publish to get a real HTTPS URL, then test each OAuth flow on the published URL — the preview iframe blocks all OAuth redirects
5. Open the Cloud tab → Logs to verify the Edge Function callback is receiving tokens and inserting rows into user_social_connections

Starter prompt:

```
Add social media integration to this app. Requirements:

1. Share button component: detect if navigator.canShare() is true; if yes, call navigator.share({ title, text, url }) with the current page's canonical URL and a UTM parameter (utm_source=app). If no, show a shadcn/ui DropdownMenu with options: 'Share to Twitter/X' (open twitter.com/intent/tweet?text=...&url=...), 'Share to LinkedIn' (open linkedin.com/sharing/shareArticle?url=...), 'Copy link' (clipboard). Show a toast on successful share or copy.

2. Connected accounts section at /settings/connections: list platforms (Twitter/X, LinkedIn, Facebook). For each: show 'Connect' button if no active row in user_social_connections, show username and 'Disconnect' button if connected. Disconnect: UPDATE user_social_connections SET revoked_at = now() then call the platform's revoke endpoint.

3. Supabase Edge Function at /functions/oauth-callback: receives the authorization code and state from the platform redirect; exchanges code for access_token and refresh_token using the platform's token endpoint; upserts into user_social_connections (user_id from JWT, platform, platform_user_id, username, access_token, refresh_token, scope, expires_at).

4. Token refresh helper: before any API call using a stored token, check if expires_at is within 5 minutes; if so, call the platform's refresh endpoint and UPDATE the row with the new token.

5. RLS on user_social_connections: users can only SELECT, INSERT, UPDATE, DELETE their own rows.

Handle these UI states: idle, redirecting to platform, callback processing, connected, error (access denied, token expired, platform API error).
```

Limitations:

- OAuth redirect URIs must be the published URL — every platform's OAuth flow breaks in the Lovable preview iframe; Facebook Login explicitly rejects iframe contexts
- Lovable Cloud Supabase tokens are not visible in the Supabase Dashboard — manage Edge Functions and RLS through Lovable's Cloud tab only
- Complex multi-platform token rotation (all platforms refreshing simultaneously for one user) may require a follow-up prompt to fix race conditions

### V0 — fit 4/10, 8–12 hours

Next.js generateMetadata() for Open Graph is native to V0 projects. Social login via Supabase Auth or Auth.js v5. Web Share API in a 'use client' component. Clean shadcn/ui component composition for share dropdowns and connected accounts UI.

1. Prompt V0 with the spec below to generate the share button component, the connected accounts settings page, the OAuth callback API route, and the Open Graph metadata helpers
2. Add your Supabase environment variables in the Vars panel: NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY
3. Add platform credentials as environment variables: TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET, LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET, and so on for each platform
4. Run the SQL schema from this page in the Supabase SQL editor to create user_social_connections with RLS
5. Deploy to Vercel and register the deployed domain's /api/auth/callback/[platform] URL in each platform's developer console — then test OAuth flows on the deployed URL

Starter prompt:

```
Build social media integration for this Next.js App Router project using Supabase Auth and shadcn/ui.

1. ShareButton client component: check navigator.canShare() — if true, call navigator.share({ title, text, url }) where url includes utm_source=share&utm_medium=app. If false, render a shadcn/ui DropdownMenu with: Twitter/X (twitter.com/intent/tweet?text=...&url=...), LinkedIn (linkedin.com/sharing/shareArticle?url=...&title=...), Facebook (facebook.com/sharer/sharer.php?u=...), Copy link (navigator.clipboard.writeText). Show success toast after share or copy.

2. Open Graph: in each page.tsx, export generateMetadata() returning { title, description, openGraph: { title, description, images: [{ url, width: 1200, height: 630 }], url, type: 'website' }, twitter: { card: 'summary_large_image', title, description, images: [url] } }.

3. /app/api/auth/callback/[platform]/route.ts: exchange authorization code for tokens, upsert into user_social_connections Supabase table (service role key), redirect to /settings/connections.

4. /app/settings/connections page (server component): fetch user_social_connections for current user; render ConnectedAccountCard for each platform showing username + disconnect button; render ConnectButton for unconnected platforms.

5. Token refresh utility: exported function refreshTokenIfNeeded(connection) — if expires_at < Date.now() + 5 minutes, POST to platform token endpoint, UPDATE user_social_connections row.

Handle states: loading (skeleton), connected (show username), disconnected (show Connect button), error (show retry with error message). Use 'use client' only where needed (ShareButton, ConnectButton).
```

Limitations:

- V0 does not scaffold Auth.js OAuth providers or Supabase Auth provider configuration automatically — register each platform's credentials manually
- Facebook SDK third-party script can conflict with Next.js Script component's loading strategy; test LCP impact after adding it
- Tailwind v3/v4 class conflicts can appear if react-big-calendar or other calendar libs are used on the same page as share UI

### Flutterflow — fit 3/10, 1–2 days

Firebase Auth supports Google, Facebook, and Apple sign-in natively in FlutterFlow with no custom code. The native share sheet uses FlutterFlow's built-in Share action (share_plus package under the hood). Social data pull and LinkedIn OAuth need custom Dart actions.

1. In FlutterFlow, go to Settings → Firebase → Authentication and enable Google, Facebook, and Apple providers — FlutterFlow auto-generates the native sign-in buttons and handles the token flow
2. For Facebook Login, add your Facebook App ID to the FlutterFlow Firebase settings and whitelist your app's bundle ID and SHA-1 key in the Meta developer console
3. Add a Share action to any button via the Action editor: choose 'Share' from the Utilities section, set the Share Text field to the content URL with UTM parameters
4. For connected social accounts (posting on behalf of users), create a Custom Action in Dart that calls the platform OAuth URL via url_launcher, handles the deep-link callback, and stores tokens in a Supabase or Firestore collection
5. Enable the share_plus and url_launcher packages in FlutterFlow's Settings → Packages if not already included

Limitations:

- LinkedIn OAuth is not supported natively in FlutterFlow Firebase Auth — requires a custom Dart action with url_launcher and a deep-link handler
- Open Graph meta tags are not applicable to mobile apps — instead, configure Dynamic Links (Firebase) or Branch.io for mobile-to-web share previews
- Social data pull (reading user's posts or follower count) requires custom Dart API calls — no built-in FlutterFlow action for platform APIs beyond auth

### Custom — fit 5/10, 1–2 weeks

Full control over token management, permission scope negotiation, social analytics, GDPR right-to-disconnect with audit logs, and multi-platform publishing from a single interface.

1. Implement per-platform OAuth 2.0 authorization code flow with PKCE (Twitter/X requires PKCE; LinkedIn and Google support it)
2. Store tokens encrypted using Supabase Vault or pgcrypto; implement token rotation with advisory locks to prevent race conditions on concurrent refresh attempts
3. Build a webhook receiver for platforms that support them (Twitter/X Account Activity API, Facebook Webhooks) to receive real-time events without polling
4. Implement GDPR right-to-disconnect: on revocation, call each platform's token revoke endpoint, delete the user_social_connections row, and write an audit log entry
5. Build a social analytics aggregator that caches platform API responses in Supabase and surfaces engagement metrics across platforms on a single dashboard

Limitations:

- Worth the investment only when social platform APIs are a core value driver — for share buttons and login alone, an AI-built path is indistinguishable in production

## Gotchas

- **Facebook OAuth fails silently in the Lovable preview iframe** — Facebook Login explicitly blocks iframe contexts for security — the OAuth popup is prevented from opening and the callback never fires. This looks identical to a misconfigured app ID, which makes debugging confusing. The same block applies to any sandboxed preview environment. Fix: Test Facebook Login only on the published Lovable URL with the exact registered domain. Add both www and non-www variants to the Facebook app's 'Valid OAuth Redirect URIs' and 'App Domains' fields in the Meta developer console. Never debug Facebook OAuth in the preview panel.
- **Social login creates duplicate accounts for the same email** — A user signs in with Google (email: alex@gmail.com), then later tries to sign in with Facebook using the same email address. Supabase Auth creates two separate user records — the second login appears to succeed but the user's data from the first login is inaccessible, causing a 'lost account' support ticket. Fix: Enable the 'Link all identities to the same user if email matches' setting in Supabase Dashboard → Authentication → Settings. This merges OAuth identities by email automatically. Also add a check in your onboarding flow: if a user signs in and already has a profile with the same email, prompt them to link rather than create.
- **Open Graph image not showing on LinkedIn after deploy** — LinkedIn caches Open Graph metadata aggressively — a newly deployed page or a page that previously had no og:image shows the wrong preview card for hours after a fix is deployed. The og:image is also ignored if it's a relative URL or served over HTTP. Fix: Ensure og:image is an absolute HTTPS URL (e.g., https://yourdomain.com/og/page-name.png) at exactly 1200x630px. After deploy, paste the page URL into LinkedIn's Post Inspector (linkedin.com/post-inspector) and click 'Inspect' to force a cache refresh. Twitter/X card validator serves the same purpose for Twitter.
- **navigator.share() throws DOMException on desktop Chrome** — Web Share API is fully supported on mobile browsers and Safari on macOS but inconsistently supported on desktop Chrome and Firefox. Calling navigator.share() without a capability check throws an unhandled DOMException that crashes the share button for users on unsupported browsers. Fix: Always guard with: if (navigator.share && navigator.canShare({ url, title, text })) { await navigator.share(...) } else { /* render dropdown fallback */ }. The else branch should always be present — never assume Web Share API availability.
- **Third-party social SDK scripts degrade Core Web Vitals** — The Facebook SDK (connect.facebook.net/en_US/sdk.js) and Twitter/X widget script (platform.twitter.com/widgets.js) are large, synchronous third-party scripts. When loaded in the document head, they delay LCP by 300–800ms and shift layout, causing measurable Core Web Vitals failures on PageSpeed Insights. Fix: In Next.js (V0), load via next/script with strategy='lazyOnload'. In Lovable/Vite, add the defer attribute and load conditionally with an Intersection Observer that only injects the script when the share component enters the viewport. Test with Lighthouse after adding any social SDK.

## Best practices

- Request the minimum OAuth scope needed — asking for write permissions when you only need login increases drop-off and complicates GDPR compliance
- Cache all social API responses in Supabase with a TTL column — rate limits are per-app, not per-user, so one heavy user can exhaust your quota for everyone
- Always include UTM parameters in share URLs (utm_source=app&utm_medium=share&utm_campaign=organic) so you can attribute traffic from social shares in your analytics
- Store the platform_user_id alongside the access_token — it's the stable identifier for the user across token refreshes and is needed to call the revoke endpoint correctly
- Implement token refresh proactively: check expires_at 5 minutes before any API call rather than waiting for a 401, which requires a full retry loop
- Provide a visible 'Disconnect' button for every connected account — users expect it and it's a GDPR requirement in the EU; soft-delete with revoked_at so you can audit past connections
- Test Open Graph preview cards on all target platforms after every deploy that changes page metadata — LinkedIn, Twitter/X, and Facebook each parse og: tags slightly differently
- Load social embed scripts lazily with Intersection Observer — each SDK is 100–200KB and any synchronous load blocks your LCP score

## Frequently asked questions

### What's the difference between social login and social account connection?

Social login (Sign in with Google) is authentication — the user proves their identity using a third-party account and your app gets their email and profile. Social account connection is authorization — the user grants your app permission to act on their behalf on that platform (read their posts, post as them). They use the same OAuth 2.0 protocol but serve different purposes and require separate token storage. Most apps need login; only apps that post or read social data on the user's behalf need account connection.

### How do I add 'Sign in with Google' to my Lovable app?

In Lovable, open the Cloud tab and go to Users & Auth. Toggle Google on. Lovable shows you the callback URL to register. Create a Google OAuth app at console.cloud.google.com, add that callback URL as an Authorized Redirect URI, copy the Client ID and Secret back into Lovable's Cloud tab, and save. That's the full setup — Supabase Auth handles the rest. Test on the published URL, not the preview.

### Can users share content to multiple platforms with one click?

On mobile, navigator.share() opens the OS share sheet which lets the user pick any installed app — so one tap covers all platforms. On desktop, a one-click multi-share to multiple platforms simultaneously isn't possible without storing connected OAuth tokens and posting server-side. The pragmatic solution for most apps is a share dropdown where each platform is one click, or a 'Copy link' button that users paste themselves.

### How do I make sure my app links preview correctly on Twitter/X and LinkedIn?

Set og:title, og:description, og:image (absolute HTTPS URL, 1200x630px), and og:url on every page. In Next.js (V0 projects), use generateMetadata() in each page.tsx to set these dynamically per page. After deploy, use Twitter's Card Validator (cards-dev.twitter.com/validator) and LinkedIn's Post Inspector (linkedin.com/post-inspector) to force a cache refresh and confirm the preview renders correctly.

### Do I need a developer account for each social platform?

Yes — each platform requires its own developer application. Google: console.cloud.google.com. GitHub: GitHub → Settings → Developer settings → OAuth Apps. Facebook/Instagram: developers.facebook.com. Twitter/X: developer.twitter.com. LinkedIn: linkedin.com/developers. Each one is free to create. Facebook and LinkedIn add extra friction: Facebook requires app review before your app can request permissions beyond basic profile, and LinkedIn's posting API requires partner approval for some scopes.

### How do I let users disconnect their social accounts?

Show a 'Disconnect' button next to each connected account in settings. On click: call the platform's token revoke endpoint (each platform has one, e.g., POST https://api.twitter.com/2/oauth2/revoke), then set revoked_at = now() on the user_social_connections row. Don't hard-delete the row — keeping it lets you audit past connections and show users when they previously connected an account.

### Is it safe to store social media OAuth tokens in Supabase?

Yes, with the right setup. Enable RLS on user_social_connections so only the owning user can read their own tokens. Store access_token and refresh_token values encrypted using Supabase Vault or pgcrypto's pgp_sym_encrypt with a key stored in Supabase Secrets. Never expose tokens to the client — all API calls using stored tokens must go through a Supabase Edge Function with the service role key.

### Can I pull a user's social media posts into my app?

Yes, but the platforms' free API access is significantly more limited than it used to be. Twitter/X's free tier barely covers login — you need the Basic tier ($100/mo approx) for meaningful read access. Facebook and Instagram require app review. LinkedIn's content API requires partner approval. If social data pull is core to your product, budget for paid API tiers and aggressive Supabase-side caching to avoid hitting rate limits.

---

Source: https://www.rapidevelopers.com/app-features/social-media-integration
© RapidDev — https://www.rapidevelopers.com/app-features/social-media-integration
