@atlas/share#

Tiny composable helpers for sharing a URL via the channels users actually use: the major socials (Twitter/X, Facebook, LinkedIn, Reddit), messengers (WhatsApp, Telegram, SMS), and email (both mailto: links and server-side send through @atlas/email).

The URL builders are pure functions — no DOM, no fetch, no SDKs. Render them in React, Mantine, server-side templates, anywhere.

Quick start#

import { share, shareUrl, shareEmail, listChannels } from "@atlas/share"
import { createEmailer } from "@atlas/email"

const content = {
  url: "https://example.com/post/123",
  title: "Look at this",
  text: "A short blurb",
  hashtags: ["atlas", "bun"],   // twitter
  via: "atlas",                  // twitter
}

shareUrl("twitter", content)
// → https://twitter.com/intent/tweet?url=…&text=…&hashtags=atlas%2Cbun&via=atlas

share(content)
// → { twitter, facebook, linkedin, reddit, whatsapp, telegram, sms, email }

listChannels()
// → [{ channel: "twitter", label: "X (Twitter)" }, ...]

// Server-side share-by-email through any @atlas/email transport
const emailer = createEmailer({ apiKey: process.env.RESEND_API_KEY, from: "[email protected]" })
await shareEmail({
  emailer,
  to: "[email protected]",
  sharerName: "Wess",
  product: "Atlas",
  message: "thought you'd like this",
  content,
})

ShareContent#

type ShareContent = {
  url: string                          // required
  title?: string                       // headline / tweet text
  text?: string                        // longer copy / body
  hashtags?: readonly string[]         // twitter — no leading '#'
  via?: string                         // twitter handle, no leading '@'
  phone?: string                       // sms — e.g. "+15551234567"
  to?:  string | readonly string[]     // mailto
  cc?:  string | readonly string[]     // mailto
  bcc?: string | readonly string[]     // mailto
}

Each channel uses whichever fields make sense for it; unknown fields are ignored. Required: url.

Channels#

ChannelURL form
twitterhttps://twitter.com/intent/tweet?url=&text=&hashtags=&via=
facebookhttps://www.facebook.com/sharer/sharer.php?u=&quote=
linkedinhttps://www.linkedin.com/sharing/share-offsite/?url=
reddithttps://www.reddit.com/submit?url=&title=
whatsapphttps://wa.me/?text= (title + text + url joined by blank lines)
telegramhttps://t.me/share/url?url=&text=
smssms:[phone]?body=
emailmailto:[to]?cc=&bcc=&subject=&body=

Server-side email#

shareEmail(opts) renders a single-column branded HTML email (uses @atlas/email's layout helper) and dispatches it through whatever Emailer you hand it. Falls back to the console transport in dev exactly like inviteEmail / passwordResetEmail.

type ShareEmailOptions = {
  emailer: Emailer
  to: string | readonly string[]
  from?: string
  replyTo?: string
  sharerName?: string
  product?: string
  message?: string
  content: ShareContent
  brand?: string
  accent?: string
}

Set replyTo to the sharer's email so the recipient can reply to them rather than the sending domain.

renderShareEmailMessage(opts) returns the same { subject, html, text } without sending — useful for previews and tests.

Adding a channel#

Add a folder under providers/<name>/index.ts that exports a ShareProvider:

export const bluesky: ShareProvider = {
  channel: "bluesky",
  label: "Bluesky",
  build: (content) => `https://bsky.app/intent/compose?text=${encodeURIComponent(content.text ?? content.url)}`,
}

Then register it in providers/index.ts and index.ts (registry + channel union).

Dependencies#

  • @atlas/email — used by shareEmail for transport + HTML layout. URL builders themselves have zero deps and can be tree-shaken if you import channels directly.

Testing#

bun test packages/share/
Canonical sourcepackages/share/AGENTS.md
Type to search guides and package references.