virality

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

/virality

/病毒式增长

Make your product spread. Social sharing, referral loops, distribution channels—every time.
让你的产品快速传播。涵盖社交分享、推荐循环、分发渠道——全流程落地。

Philosophy

核心理念

Virality is a feature, not an accident. Products don't go viral by luck. They're engineered to spread.
Every user interaction is a sharing opportunity. Completed a task? Share it. Hit a milestone? Share it. Created something? Share it.
Remove friction from sharing. One click to share. Beautiful previews. Pre-filled copy.
Measure the loop. K-factor (viral coefficient) tells you if growth is self-sustaining.
病毒式增长是一项功能,而非意外。 产品不会仅凭运气走红,而是通过精心设计实现传播。
每一次用户交互都是分享机会。 完成任务?分享它。达成里程碑?分享它。创建内容?分享它。
消除分享障碍。 一键分享、精美的预览效果、预填充文案。
衡量传播循环。 K-factor(病毒系数)可告诉你增长是否具备自我持续性。

What This Does

功能概述

Audits your product for shareability, identifies viral loop opportunities, implements sharing infrastructure, and verifies the mechanics work. Every run does the full cycle.
审计产品的分享属性,识别病毒式传播循环的机会,搭建分享基础设施,并验证机制是否有效。每次运行都会完成全流程循环。

Branching

分支管理

Assumes you start on
master
/
main
. Before making code changes:
bash
git checkout -b feat/virality-$(date +%Y%m%d)
假设你从
master
/
main
分支开始。在修改代码前:
bash
git checkout -b feat/virality-$(date +%Y%m%d)

Process

实施流程

1. Audit

1. 审计

Social Metadata Check

社交元数据检查

bash
undefined
bash
undefined

OG tags present?

OG tags present?

grep -rE "og:title|og:description|og:image"
--include=".tsx" --include=".ts" --include="*.html"
app/ src/ pages/ 2>/dev/null | head -5
grep -rE "og:title|og:description|og:image"
--include=".tsx" --include=".ts" --include="*.html"
app/ src/ pages/ 2>/dev/null | head -5

Twitter cards?

Twitter cards?

grep -rE "twitter:card|twitter:title|twitter:image"
--include=".tsx" --include=".ts"
app/ src/ pages/ 2>/dev/null | head -5
grep -rE "twitter:card|twitter:title|twitter:image"
--include=".tsx" --include=".ts"
app/ src/ pages/ 2>/dev/null | head -5

Dynamic OG images?

Dynamic OG images?

[ -f "app/api/og/route.tsx" ] || [ -d "pages/api/og" ] && echo "✓ OG image endpoint" || echo "✗ OG image endpoint"
[ -f "app/api/og/route.tsx" ] || [ -d "pages/api/og" ] && echo "✓ OG image endpoint" || echo "✗ OG image endpoint"

Metadata in layout?

Metadata in layout?

grep -q "generateMetadata|metadata" app/layout.tsx 2>/dev/null && echo "✓ Root metadata" || echo "✗ Root metadata"
undefined
grep -q "generateMetadata|metadata" app/layout.tsx 2>/dev/null && echo "✓ Root metadata" || echo "✗ Root metadata"
undefined

Share Mechanics Check

分享机制检查

bash
undefined
bash
undefined

Share buttons exist?

Share buttons exist?

grep -rE "share|Share|navigator.share|clipboard"
--include=".tsx" --include=".ts"
components/ src/ 2>/dev/null | head -5
grep -rE "share|Share|navigator.share|clipboard"
--include=".tsx" --include=".ts"
components/ src/ 2>/dev/null | head -5

Shareable URLs?

Shareable URLs?

grep -rE "shareUrl|shareLink|getShareUrl"
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
grep -rE "shareUrl|shareLink|getShareUrl"
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5

Deep linking?

Deep linking?

grep -rE "searchParams|useSearchParams|[.]"
--include="
.tsx" --include="*.ts"
app/ pages/ 2>/dev/null | head -5
undefined
grep -rE "searchParams|useSearchParams|[.]"
--include="
.tsx" --include="*.ts"
app/ pages/ 2>/dev/null | head -5
undefined

Referral System Check

推荐系统检查

bash
undefined
bash
undefined

Referral codes?

Referral codes?

grep -rE "referral|invite|inviteCode|refCode"
--include=".tsx" --include=".ts" --include="*.sql"
. 2>/dev/null | grep -v node_modules | head -5
grep -rE "referral|invite|inviteCode|refCode"
--include=".tsx" --include=".ts" --include="*.sql"
. 2>/dev/null | grep -v node_modules | head -5

Attribution tracking?

Attribution tracking?

grep -rE "utm_|referrer|attribution"
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
undefined
grep -rE "utm_|referrer|attribution"
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
undefined

Distribution Readiness Check

分发就绪检查

bash
undefined
bash
undefined

Product Hunt assets?

Product Hunt assets?

[ -f "public/product-hunt-logo.png" ] || [ -d "public/launch" ] && echo "✓ Launch assets" || echo "✗ Launch assets"
[ -f "public/product-hunt-logo.png" ] || [ -d "public/launch" ] && echo "✓ Launch assets" || echo "✗ Launch assets"

Press kit / media assets?

Press kit / media assets?

[ -d "public/press" ] || [ -d "public/media" ] && echo "✓ Press kit" || echo "✗ Press kit"
[ -d "public/press" ] || [ -d "public/media" ] && echo "✓ Press kit" || echo "✗ Press kit"

Changelog / updates page?

Changelog / updates page?

[ -f "app/changelog/page.tsx" ] || [ -f "pages/changelog.tsx" ] && echo "✓ Changelog page" || echo "✗ Changelog page"
undefined
[ -f "app/changelog/page.tsx" ] || [ -f "pages/changelog.tsx" ] && echo "✓ Changelog page" || echo "✗ Changelog page"
undefined

2. Plan

2. 规划

Every shareable product needs:
Essential (every product):
  • Open Graph tags on all public pages
  • Twitter Card tags
  • Dynamic OG images for key content
  • Copy-to-clipboard share URLs
  • Mobile-friendly share (Web Share API)
For user-generated content:
  • Unique shareable URLs per item
  • Beautiful social previews per item
  • One-click sharing after creation
  • "Share your [thing]" prompts
For growth:
  • Referral system with tracking
  • Invite flows
  • Attribution (UTM) tracking
  • K-factor measurement
For launches:
  • Product Hunt assets and timing
  • Press kit with logos/screenshots
  • Changelog page for updates
  • Social proof (testimonials, stats)
所有具备分享属性的产品都需要:
基础配置(所有产品适用):
  • 所有公开页面添加Open Graph标签
  • Twitter Card标签
  • 核心内容的动态OG图片
  • 支持一键复制的分享URL
  • 移动端友好的分享功能(Web Share API)
针对用户生成内容:
  • 每个内容项对应唯一的分享URL
  • 每个内容项对应精美的社交预览
  • 内容创建完成后一键分享
  • “分享你的[内容]”提示
针对增长需求:
  • 带追踪功能的推荐系统
  • 邀请流程
  • 归因(UTM)追踪
  • K因子衡量
针对产品发布:
  • Product Hunt相关素材与时间规划
  • 包含Logo/截图的媒体包
  • 更新日志页面
  • 社交证明(用户评价、数据统计)

3. Execute

3. 实施

Add Root Metadata

添加根元数据

typescript
// app/layout.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL!),
  title: {
    default: 'Your Product - Tagline',
    template: '%s | Your Product',
  },
  description: 'One sentence that makes people want to try it.',
  openGraph: {
    type: 'website',
    locale: 'en_US',
    siteName: 'Your Product',
    images: ['/og-default.png'],
  },
  twitter: {
    card: 'summary_large_image',
    creator: '@yourhandle',
  },
};
typescript
// app/layout.tsx
import type { Metadata } from 'next';

export const metadata: Metadata = {
  metadataBase: new URL(process.env.NEXT_PUBLIC_APP_URL!),
  title: {
    default: 'Your Product - Tagline',
    template: '%s | Your Product',
  },
  description: 'One sentence that makes people want to try it.',
  openGraph: {
    type: 'website',
    locale: 'en_US',
    siteName: 'Your Product',
    images: ['/og-default.png'],
  },
  twitter: {
    card: 'summary_large_image',
    creator: '@yourhandle',
  },
};

Create Dynamic OG Image Endpoint

创建动态OG图片端点

typescript
// app/api/og/route.tsx
import { ImageResponse } from 'next/og';

export const runtime = 'edge';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const title = searchParams.get('title') ?? 'Your Product';
  const description = searchParams.get('description') ?? '';

  return new ImageResponse(
    (
      <div
        style={{
          height: '100%',
          width: '100%',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: '#000',
          color: '#fff',
          fontFamily: 'system-ui',
        }}
      >
        <div style={{ fontSize: 60, fontWeight: 'bold' }}>{title}</div>
        {description && (
          <div style={{ fontSize: 30, marginTop: 20, opacity: 0.8 }}>
            {description}
          </div>
        )}
      </div>
    ),
    { width: 1200, height: 630 }
  );
}
typescript
// app/api/og/route.tsx
import { ImageResponse } from 'next/og';

export const runtime = 'edge';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const title = searchParams.get('title') ?? 'Your Product';
  const description = searchParams.get('description') ?? '';

  return new ImageResponse(
    (
      <div
        style={{
          height: '100%',
          width: '100%',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          backgroundColor: '#000',
          color: '#fff',
          fontFamily: 'system-ui',
        }}
      >
        <div style={{ fontSize: 60, fontWeight: 'bold' }}>{title}</div>
        {description && (
          <div style={{ fontSize: 30, marginTop: 20, opacity: 0.8 }}>
            {description}
          </div>
        )}
      </div>
    ),
    { width: 1200, height: 630 }
  );
}

Add Page-Specific Metadata

添加页面专属元数据

typescript
// app/[slug]/page.tsx
import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const item = await getItem(params.slug);

  return {
    title: item.title,
    description: item.description,
    openGraph: {
      title: item.title,
      description: item.description,
      images: [`/api/og?title=${encodeURIComponent(item.title)}`],
    },
  };
}
typescript
// app/[slug]/page.tsx
import type { Metadata } from 'next';

export async function generateMetadata({ params }): Promise<Metadata> {
  const item = await getItem(params.slug);

  return {
    title: item.title,
    description: item.description,
    openGraph: {
      title: item.title,
      description: item.description,
      images: [`/api/og?title=${encodeURIComponent(item.title)}`],
    },
  };
}

Create Share Component

创建分享组件

typescript
// components/share-button.tsx
'use client';

import { useState } from 'react';

interface ShareButtonProps {
  url: string;
  title: string;
  text?: string;
}

export function ShareButton({ url, title, text }: ShareButtonProps) {
  const [copied, setCopied] = useState(false);

  const share = async () => {
    // Try native share first (mobile)
    if (navigator.share) {
      try {
        await navigator.share({ url, title, text });
        return;
      } catch {
        // User cancelled or not supported
      }
    }

    // Fallback to clipboard
    await navigator.clipboard.writeText(url);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <button onClick={share}>
      {copied ? 'Copied!' : 'Share'}
    </button>
  );
}
typescript
// components/share-button.tsx
'use client';

import { useState } from 'react';

interface ShareButtonProps {
  url: string;
  title: string;
  text?: string;
}

export function ShareButton({ url, title, text }: ShareButtonProps) {
  const [copied, setCopied] = useState(false);

  const share = async () => {
    // Try native share first (mobile)
    if (navigator.share) {
      try {
        await navigator.share({ url, title, text });
        return;
      } catch {
        // User cancelled or not supported
      }
    }

    // Fallback to clipboard
    await navigator.clipboard.writeText(url);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <button onClick={share}>
      {copied ? 'Copied!' : 'Share'}
    </button>
  );
}

Add Share Prompts at Key Moments

在关键节点添加分享提示

typescript
// After user completes an action
function onComplete() {
  // Show share prompt
  showShareModal({
    title: "You did the thing!",
    prompt: "Share your achievement?",
    url: `${baseUrl}/share/${resultId}`,
    prefilledText: "I just [did thing] with @YourProduct!",
  });
}
typescript
// After user completes an action
function onComplete() {
  // Show share prompt
  showShareModal({
    title: "You did the thing!",
    prompt: "Share your achievement?",
    url: `${baseUrl}/share/${resultId}`,
    prefilledText: "I just [did thing] with @YourProduct!",
  });
}

Implement Referral System

实施推荐系统

typescript
// lib/referrals.ts
export function generateReferralCode(userId: string): string {
  // Short, memorable codes
  return `${userId.slice(0, 4).toUpperCase()}${randomChars(4)}`;
}

export function getReferralUrl(code: string): string {
  return `${process.env.NEXT_PUBLIC_APP_URL}?ref=${code}`;
}

// Track on signup
export async function trackReferral(newUserId: string, refCode: string | null) {
  if (!refCode) return;

  const referrer = await getUserByRefCode(refCode);
  if (!referrer) return;

  await db.referrals.create({
    referrerId: referrer.id,
    referredId: newUserId,
    code: refCode,
    createdAt: new Date(),
  });

  // Reward referrer (if applicable)
  await grantReferralReward(referrer.id);
}
typescript
// lib/referrals.ts
export function generateReferralCode(userId: string): string {
  // Short, memorable codes
  return `${userId.slice(0, 4).toUpperCase()}${randomChars(4)}`;
}

export function getReferralUrl(code: string): string {
  return `${process.env.NEXT_PUBLIC_APP_URL}?ref=${code}`;
}

// Track on signup
export async function trackReferral(newUserId: string, refCode: string | null) {
  if (!refCode) return;

  const referrer = await getUserByRefCode(refCode);
  if (!referrer) return;

  await db.referrals.create({
    referrerId: referrer.id,
    referredId: newUserId,
    code: refCode,
    createdAt: new Date(),
  });

  // Reward referrer (if applicable)
  await grantReferralReward(referrer.id);
}

Track Attribution (UTMs)

追踪归因(UTMs)

typescript
// middleware.ts or on page load
export function captureAttribution() {
  if (typeof window === 'undefined') return;

  const params = new URLSearchParams(window.location.search);
  const attribution = {
    utm_source: params.get('utm_source'),
    utm_medium: params.get('utm_medium'),
    utm_campaign: params.get('utm_campaign'),
    ref: params.get('ref'),
    referrer: document.referrer,
  };

  // Store for later (signup, conversion)
  sessionStorage.setItem('attribution', JSON.stringify(attribution));
}
typescript
// middleware.ts or on page load
export function captureAttribution() {
  if (typeof window === 'undefined') return;

  const params = new URLSearchParams(window.location.search);
  const attribution = {
    utm_source: params.get('utm_source'),
    utm_medium: params.get('utm_medium'),
    utm_campaign: params.get('utm_campaign'),
    ref: params.get('ref'),
    referrer: document.referrer,
  };

  // Store for later (signup, conversion)
  sessionStorage.setItem('attribution', JSON.stringify(attribution));
}

Measure K-Factor

衡量K因子

typescript
// K-factor = invites sent per user × conversion rate
// K > 1 means viral growth

export async function calculateKFactor(timeWindow: string = '30d') {
  const activeUsers = await countActiveUsers(timeWindow);
  const invitesSent = await countInvitesSent(timeWindow);
  const inviteConversions = await countInviteConversions(timeWindow);

  const invitesPerUser = invitesSent / activeUsers;
  const conversionRate = inviteConversions / invitesSent;
  const kFactor = invitesPerUser * conversionRate;

  return {
    kFactor,
    invitesPerUser,
    conversionRate,
    isViral: kFactor > 1,
  };
}
typescript
// K-factor = invites sent per user × conversion rate
// K > 1 means viral growth

export async function calculateKFactor(timeWindow: string = '30d') {
  const activeUsers = await countActiveUsers(timeWindow);
  const invitesSent = await countInvitesSent(timeWindow);
  const inviteConversions = await countInviteConversions(timeWindow);

  const invitesPerUser = invitesSent / activeUsers;
  const conversionRate = inviteConversions / invitesSent;
  const kFactor = invitesPerUser * conversionRate;

  return {
    kFactor,
    invitesPerUser,
    conversionRate,
    isViral: kFactor > 1,
  };
}

4. Verify

4. 验证

Test OG tags:
bash
undefined
测试OG标签:
bash
undefined

Use a validator

Use a validator

open "https://www.opengraph.xyz/url/$(echo $YOUR_URL | jq -sRr @uri)"
open "https://www.opengraph.xyz/url/$(echo $YOUR_URL | jq -sRr @uri)"

Or curl and check

Or curl and check

curl -s "$YOUR_URL" | grep -E "og:|twitter:" | head -10

**Test dynamic OG images:**
```bash
curl -s "$YOUR_URL" | grep -E "og:|twitter:" | head -10

**测试动态OG图片:**
```bash

Check the endpoint works

Check the endpoint works

Should return image/png content-type

Should return image/png content-type


**Test share flow:**
1. Create/complete something in the app
2. Click share button
3. Verify URL is correct and copyable
4. Paste URL in Twitter/LinkedIn preview checker
5. Verify preview looks good

**Test referral flow:**
1. Get your referral link
2. Open in incognito
3. Sign up
4. Verify referral tracked
5. Verify referrer credited

**Test mobile share:**
1. Open on mobile device
2. Click share
3. Verify native share sheet appears
4. Complete share to an app

If any verification fails, go back and fix it.

**测试分享流程:**
1. 在应用内创建/完成某项操作
2. 点击分享按钮
3. 验证URL正确且可复制
4. 将URL粘贴到Twitter/LinkedIn预览工具中
5. 确认预览效果符合预期

**测试推荐流程:**
1. 获取你的推荐链接
2. 在隐身模式下打开
3. 完成注册
4. 验证推荐关系已被追踪
5. 验证推荐人已获得奖励

**测试移动端分享:**
1. 在移动设备上打开应用
2. 点击分享按钮
3. 确认原生分享面板弹出
4. 完成分享到某款应用

如果任何验证步骤失败,返回修改后重新验证。

Viral Loop Patterns

病毒式循环模式

The Creation Loop

创建循环

User creates something → Prompted to share → Friend sees → Creates their own → ...
Best for: Tools, generators, creative apps
用户创建内容 → 触发分享提示 → 好友看到 → 创建自己的内容 → ...
适用场景:工具类、生成器、创意应用

The Achievement Loop

成就循环

User hits milestone → Shareable achievement card → Social proof → Friend tries → ...
Best for: Games, learning apps, fitness apps
用户达成里程碑 → 生成可分享的成就卡片 → 形成社交证明 → 好友尝试使用 → ...
适用场景:游戏、学习应用、健身应用

The Invitation Loop

邀请循环

User invites friend → Friend joins → Both rewarded → Friend invites → ...
Best for: Marketplaces, social apps, collaboration tools
用户邀请好友 → 好友加入 → 双方获得奖励 → 好友继续邀请 → ...
适用场景:平台类、社交应用、协作工具

The Content Loop

内容循环

User creates content → Content has product watermark → Viewer sees → Visits product → ...
Best for: Design tools, video editors, meme generators
用户创建内容 → 内容带有产品水印 → 浏览者看到 → 访问产品 → ...
适用场景:设计工具、视频编辑器、表情包生成器

Launch Checklist

发布检查清单

For Product Hunt and similar:
  • OG image at exactly 1200x630
  • Tagline under 60 characters
  • Description under 260 characters
  • 4-6 screenshots/GIFs
  • Maker comment prepared
  • First comment prepared
  • Launch day = Tuesday/Wednesday
  • Launch time = 12:01 AM PT
  • Notify your network to upvote early
针对Product Hunt及类似平台:
  • OG图片尺寸严格为1200x630
  • 标语不超过60个字符
  • 描述不超过260个字符
  • 4-6张截图/GIF
  • 准备好开发者评论
  • 准备好第一条评论
  • 发布日期选择周二/周三
  • 发布时间为太平洋时间凌晨12:01
  • 提前通知你的社交网络进行点赞

CLI Tools

CLI工具

bash
undefined
bash
undefined

Validate OG tags

Validate OG tags

npx open-graph-scraper https://yoursite.com
npx open-graph-scraper https://yoursite.com

Generate social images locally

Generate social images locally

npx @vercel/og-image "Title" --output og.png
npx @vercel/og-image "Title" --output og.png

Check Twitter card

Check Twitter card

Related Skills

相关技能

  • launch-strategy
    - Product launch planning
  • social-content
    - Social media content creation
  • marketing-ideas
    - Growth tactics
  • launch-strategy
    - 产品发布规划
  • social-content
    - 社交媒体内容创作
  • marketing-ideas
    - 增长策略