
Most social share button plugins add bloat, external dependencies, and unpredictable behavior. On a Framer CMS site, that usually means slower pages, tracking scripts you didn't ask for, and share previews that look wrong on LinkedIn or Slack
The good news is that share buttons are fundamentally just links to platform share dialogs — and the preview card (title, image, description) is controlled by Open Graph metadata, which Framer handles natively with CMS-dynamic variables. You can build fast, reliable share buttons without third-party widgets.
This guide shows you how to set up Open Graph correctly for your Framer CMS posts, then add share buttons using the BRIX Share Overrides — a set of lightweight Code Overrides that handle Facebook, X, LinkedIn, Email, native mobile sharing, and copy-to-clipboard functionality.

Adding share functionality to your blog posts creates distribution opportunities you don't get from just publishing content.
Before implementing anything, it helps to understand the two separate pieces that make sharing work.
Share action: Your button opens a platform's share endpoint (like LinkedIn's share URL) and passes the page URL. That's all the button does — it controls where the user goes when they click.
Share preview: The card that appears in LinkedIn feeds, Slack messages, or X posts is generated by the platform scraping your page's Open Graph metadata. The title, description, and thumbnail come from OG tags — not from parameters in the share URL.
This separation is why most "share widget" complexity is unnecessary. Platforms ignore custom title/image parameters in share URLs and scrape your page's OG tags instead. So the correct approach is: configure Open Graph properly once, then use simple share overrides. No heavy scripts required.
If you skip this section, your share buttons will "work" but shares will look wrong. Open Graph controls the preview card on LinkedIn, Facebook, X, Slack, and most other platforms.

These defaults apply across the site unless overridden at the page level.

For CMS posts, you want each item to have unique metadata pulled from its fields.

This creates unique meta tags for every CMS item automatically.

Framer recommends a 1200 × 630 aspect ratio for social preview images. Keep important content centered since platforms crop differently.
For more reliable preview rendering, you can add og:image:width and og:image:height meta tags in your page's custom code. These help crawlers render OG images faster and avoid "missing image" issues.

Before assuming anything is broken, use Framer's Meta Check tool to see exactly how your page appears on Google, X, Slack, LinkedIn, and Threads.
After updating OG settings, platforms may show cached previews until you force a rescrape:
For Facebook: Use the Meta Sharing Debugger — paste your URL and click Scrape Again.
For LinkedIn: Use LinkedIn Post Inspector — paste your URL to refresh the cached preview.
For X: Use Meta Check to preview how your card will appear — it's more reliable than X's deprecated Card Validator.
LinkedIn caching issues are particularly common — if Meta Check shows the correct image but LinkedIn doesn't, force a rescrape and test with a brand-new share.
The BRIX Share Overrides use Framer's native Code Override system. You create your share button UI visually in the Designer, then apply overrides to make each button share the current page URL.
The overrides are completely self-contained — no external libraries, no CDN dependencies, no third-party requests. Everything runs from the single override file you create. This means:
When a user clicks a share button, the override reads the canonical URL (avoiding UTM parameter fragmentation) and the OG title (for cleaner share text), properly encodes them for the target platform, and opens the share dialog. On desktop, it opens a centered popup window with proper security settings. On mobile, it opens a new tab (better UX than tiny popups).
Overrides only run in Preview and Published mode — they don't execute on the canvas, which is by design.
You can use any elements as share buttons — the overrides don't care about element type, only that they can receive a click handler.
Mobile-only Native Share button (optional): For mobile users, add a separate “Share” icon alongside your social icons and wrap it in its own Frame (just like the others). Set this Frame to be visible only on the mobile breakpoint and hidden on tablet/desktop, since native sharing relies on the Web Share API, which is primarily supported on mobile. Keep your regular network buttons as the universal fallback.
Wrapping icons in Frames is a practical tip that reduces weird override conflicts, especially with icon components that have their own internal behavior.


/**
* BRIX Templates — Framer Share Overrides
* ----------------------------------------------------------------------------
* Enables social sharing through Code Overrides. Self-contained with no
* external dependencies. Supports Facebook, X, LinkedIn, Email, native
* Web Share API, and copy-to-clipboard functionality.
*
* Usage: Apply overrides (withBRIXShareFacebook, withBRIXShareX, etc.)
* to your icon Frames via the Code Overrides panel.
*
* Version: 1.1.0
* Author: BRIX Templates
*/
import { forwardRef, type ComponentType } from "react"
// -----------------------------------------------------------------------------
// Configuration
// -----------------------------------------------------------------------------
const config = {
popupWidth: 580,
popupHeight: 520,
mobileBreakpoint: 767,
}
// -----------------------------------------------------------------------------
// Helpers
// -----------------------------------------------------------------------------
function isMobile(): boolean {
return (
window.matchMedia?.(`(max-width: ${config.mobileBreakpoint}px)`)
?.matches ?? false
)
}
function getCanonicalUrl(): string {
const canonical = document.querySelector(
'link[rel="canonical"]'
) as HTMLLinkElement
if (canonical?.href) return canonical.href
return window.location.href.split("#")[0]
}
function getBestTitle(): string {
const ogTitle = (document.querySelector(
'meta[property="og:title"]'
) as HTMLMetaElement) ||
(document.querySelector(
'meta[name="twitter:title"]'
) as HTMLMetaElement)
if (ogTitle?.content) return ogTitle.content
return document.title || ""
}
function openShareWindow(url: string): void {
if (isMobile()) {
const newTab = window.open(url, "_blank", "noopener,noreferrer")
if (newTab) newTab.opener = null
return
}
const screenLeft = window.screenLeft ?? window.screenX
const screenTop = window.screenTop ?? window.screenY
const windowWidth =
window.innerWidth ?? document.documentElement.clientWidth
const windowHeight =
window.innerHeight ?? document.documentElement.clientHeight
const left = Math.round(
windowWidth / 2 - config.popupWidth / 2 + screenLeft
)
const top = Math.round(
windowHeight / 2 - config.popupHeight / 2 + screenTop
)
const features = [
"scrollbars=yes",
`width=${config.popupWidth}`,
`height=${config.popupHeight}`,
`top=${top}`,
`left=${left}`,
"noopener=yes",
"noreferrer=yes",
].join(",")
const popup = window.open(url, "share", features)
if (popup) {
popup.opener = null
popup.focus?.()
}
}
function buildShareUrl(
network: string,
pageUrl: string,
pageTitle: string
): string | null {
const encodedUrl = encodeURIComponent(pageUrl)
const encodedTitle = encodeURIComponent(pageTitle)
switch (network) {
case "facebook":
return `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`
case "x":
return `https://twitter.com/intent/tweet?url=${encodedUrl}&text=${encodedTitle}`
case "linkedin":
return `https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`
case "email":
return `mailto:?subject=${encodedTitle}&body=${encodeURIComponent(pageTitle + "\n\n" + pageUrl)}`
default:
return null
}
}
// -----------------------------------------------------------------------------
// Share handler (reusable logic)
// -----------------------------------------------------------------------------
function handleShareClick(network: string, existingOnClick?: Function) {
return (e: React.MouseEvent) => {
e?.preventDefault?.()
const pageUrl = getCanonicalUrl()
const pageTitle = getBestTitle()
const shareUrl = buildShareUrl(network, pageUrl, pageTitle)
if (shareUrl) {
openShareWindow(shareUrl)
}
existingOnClick?.(e)
}
}
// -----------------------------------------------------------------------------
// Exported Share Overrides — Each defined explicitly for Framer detection
// -----------------------------------------------------------------------------
export function withBRIXShareFacebook(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
return (
<Component
ref={ref}
{...props}
onClick={handleShareClick("facebook", props?.onClick)}
/>
)
})
}
export function withBRIXShareX(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
return (
<Component
ref={ref}
{...props}
onClick={handleShareClick("x", props?.onClick)}
/>
)
})
}
export function withBRIXShareLinkedIn(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
return (
<Component
ref={ref}
{...props}
onClick={handleShareClick("linkedin", props?.onClick)}
/>
)
})
}
export function withBRIXShareEmail(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
return (
<Component
ref={ref}
{...props}
onClick={handleShareClick("email", props?.onClick)}
/>
)
})
}
// -----------------------------------------------------------------------------
// Native Share Override (Web Share API)
// -----------------------------------------------------------------------------
export function withBRIXShareNative(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
const handleClick = async (e: React.MouseEvent) => {
e?.preventDefault?.()
if (!navigator.share) {
props?.onClick?.(e)
return
}
const pageUrl = getCanonicalUrl()
const pageTitle = getBestTitle()
try {
await navigator.share({
title: pageTitle,
text: pageTitle,
url: pageUrl,
})
} catch {
// User cancelled or share failed
}
props?.onClick?.(e)
}
return <Component ref={ref} {...props} onClick={handleClick} />
})
}
// -----------------------------------------------------------------------------
// Copy Link Override
// -----------------------------------------------------------------------------
export function withBRIXCopyLink(Component: ComponentType): ComponentType {
return forwardRef((props: any, ref) => {
const handleClick = async (e: React.MouseEvent) => {
e?.preventDefault?.()
try {
await navigator.clipboard.writeText(getCanonicalUrl())
} catch {
// Clipboard API failed — silent fail
}
props?.onClick?.(e)
}
return <Component ref={ref} {...props} onClick={handleClick} />
})
}The override file exports these functions that you can apply to your share buttons:
withBRIXShareFacebook — Opens Facebook's share dialog with the current page URL. Facebook pulls the preview from your Open Graph tags.
withBRIXShareX — Opens X (Twitter) with the page URL and title as prefilled tweet text. The title is properly encoded to handle special characters.
withBRIXShareLinkedIn — Opens LinkedIn's share dialog. LinkedIn pulls all preview data from Open Graph tags.
withBRIXShareEmail — Opens the user's default email client with the page title as subject and a clean body containing the title and URL.
withBRIXShareNative — Triggers the Web Share API on supported devices (primarily mobile). Shows the native share sheet with all available apps. On unsupported browsers, it does nothing — keep your regular share buttons visible as fallback.
withBRIXCopyLink — Copies the current page URL to the clipboard. Useful as a complement to your share buttons for users who just want the link.

Apply the Native override: Select the Frame wrapping your mobile “Share” icon, then choose BRIXShareOverridesThe good news is that share buttons are fundamentally just links to platform share dialogs — and the preview card (title, image, description) is controlled by Open Graph metadata, which Framer handles natively with CMS-dynamic variables. You can build fast, reliable share buttons without third-party widgets. On supported devices, this opens the native share sheet; on unsupported browsers it may do nothing, so keep the button mobile-only and rely on your standard Facebook/X/LinkedIn buttons elsewhere.
Remember: overrides only run in Preview and Published mode. Test by clicking Preview or publishing your site — buttons won't work on the canvas.
Don't assume everything works — previews and buttons can fail silently.

The cleanest approach is using Code Overrides that share the current page URL dynamically. Build your share button UI visually in Framer Designer (icons wrapped in Frames), then apply the BRIX Share Overrides to each button. This works automatically across all CMS posts since the override reads the URL at click time. Also configure your CMS page's Open Graph settings so previews display the correct title, description, and image. Test in Preview mode since overrides don't run on the canvas.
Share buttons control the click action — when someone clicks "Share on LinkedIn," the button opens LinkedIn's share dialog with your page URL. Social previews control what the shared post looks like in feeds and messages — the title, description, and thumbnail image. Platforms scrape this data from your page's Open Graph meta tags. If the preview looks wrong, fixing the share button won't help — you need to fix your Open Graph settings in Framer's Page Settings and validate with Meta Check.
Yes. The BRIX Share Overrides are completely self-contained Code Overrides with no external dependencies — no CDN links, no tracking scripts, no third-party requests. Build your icon UI as normal Framer layers, apply the overrides, and publish. You get Facebook, X, LinkedIn, Email, native mobile sharing, and copy-to-clipboard functionality without any plugin overhead. If performance and independence are priorities, overrides are the correct approach for Framer.
Add an Image field to your CMS Collection (like "Cover Image"), upload images for each CMS item, then open the CMS page's Page Settings and set Social Preview to CMS Variables pointing to that image field. Framer recommends a 1200 × 630 aspect ratio. After publishing, validate the post URL in Meta Check to confirm the correct image is being scraped. This solves most "LinkedIn shows nothing" problems.
Usually one of three issues: (1) the CMS page isn't using CMS Variables for Social Preview, (2) the specific CMS item doesn't have an image uploaded to that field, or (3) LinkedIn is showing a cached older scrape. Fix the first two in Framer's Page Settings, validate with Meta Check, then force a rescrape with LinkedIn Post Inspector. LinkedIn caching is notoriously aggressive — if Meta Check shows the right image but LinkedIn doesn't, the cache is the problem.
Use Code Overrides that read the URL at click time. The BRIX Share Overrides use canonical URL detection (falling back to the current URL without hash fragments) so each CMS post automatically shares its own URL. This eliminates the "always shares homepage" bug that happens when you hardcode URLs or use static Link values. Apply the appropriate override to each share button Frame and test in Preview mode.
Use both, but treat the Web Share API as progressive enhancement. The withBRIXShareNative override triggers the native share sheet on supported devices (primarily mobile), giving users access to all their apps. But Web Share API isn't universal — desktop support is limited and it requires HTTPS. Keep your regular Facebook, X, and LinkedIn buttons visible as fallback. The native option improves mobile UX without replacing your baseline functionality.
Always URL-encode values passed to share endpoints. The BRIX Share Overrides handle this automatically with encodeURIComponent() for both the URL and title. Characters like &, ?, and non-English text get encoded properly so share URLs don't break. If you're seeing issues, verify you're using the override method rather than manually constructing share URLs in Link fields.
Add an icon for "Copy" next to your share icons, wrap it in a Frame, and apply the withBRIXCopyLink override. This writes the current page URL to the clipboard when clicked. It's a high-value UX addition since many users just want the link without opening a share dialog. The override handles clipboard API calls silently — if the API fails in certain contexts, it fails gracefully without breaking anything.
Code Overrides don't execute on the Framer canvas — they only run in Preview and Published mode. This is by design. Click the Preview button or publish your site, then test your share buttons. If they still don't work after previewing, check that the override is actually applied to the element (visible in the Code Overrides panel) and that you've selected the correct override function from the file.
The clean way to add social share buttons in Framer is straightforward: configure Open Graph dynamically per CMS item so previews display correctly, then use the BRIX Share Overrides to handle the click action. This gives you fast pages, correct previews, and share functionality that doesn't depend on bloated third-party plugins.
The overrides are completely self-contained — no external dependencies, no tracking, no CDN links. Create your override file once, apply the overrides to your share buttons, and they work across every CMS post automatically.
If you need help implementing social sharing across your Framer CMS — including custom share button styling, Open Graph debugging, and preview optimization — our Framer agency can set it up properly.

Capture page URL and browser title in Framer form submissions using hidden fields and the BRIX Form Source Tracker.

Learn how to track UTM parameters in Framer using native tools and a persistent attribution script for cross-session tracking.

Add IDX MLS listings to Framer: provider options, who supports Framer, widget embedding, and Framer-specific technical details.