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 /. Before making code changes:
mastermainbash
git checkout -b feat/virality-$(date +%Y%m%d)假设你从/分支开始。在修改代码前:
mastermainbash
git checkout -b feat/virality-$(date +%Y%m%d)Process
实施流程
1. Audit
1. 审计
Social Metadata Check
社交元数据检查
bash
undefinedbash
undefinedOG 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
--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
--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
--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
--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"
undefinedgrep -q "generateMetadata|metadata" app/layout.tsx 2>/dev/null && echo "✓ Root metadata" || echo "✗ Root metadata"
undefinedShare Mechanics Check
分享机制检查
bash
undefinedbash
undefinedShare buttons exist?
Share buttons exist?
grep -rE "share|Share|navigator.share|clipboard"
--include=".tsx" --include=".ts"
components/ src/ 2>/dev/null | head -5
--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
--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
--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
--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
--include=".tsx" --include="*.ts"
app/ pages/ 2>/dev/null | head -5
undefinedgrep -rE "searchParams|useSearchParams|[.]"
--include=".tsx" --include="*.ts"
app/ pages/ 2>/dev/null | head -5
--include=".tsx" --include="*.ts"
app/ pages/ 2>/dev/null | head -5
undefinedReferral System Check
推荐系统检查
bash
undefinedbash
undefinedReferral codes?
Referral codes?
grep -rE "referral|invite|inviteCode|refCode"
--include=".tsx" --include=".ts" --include="*.sql"
. 2>/dev/null | grep -v node_modules | head -5
--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
--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
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
undefinedgrep -rE "utm_|referrer|attribution"
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
--include=".tsx" --include=".ts"
. 2>/dev/null | grep -v node_modules | head -5
undefinedDistribution Readiness Check
分发就绪检查
bash
undefinedbash
undefinedProduct 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"
undefined2. 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
undefinedUse 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:**
```bashcurl -s "$YOUR_URL" | grep -E "og:|twitter:" | head -10
**测试动态OG图片:**
```bashCheck the endpoint works
Check the endpoint works
curl -I "https://yoursite.com/api/og?title=Test"
curl -I "https://yoursite.com/api/og?title=Test"
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
undefinedbash
undefinedValidate 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
undefinedundefinedRelated Skills
相关技能
- - Product launch planning
launch-strategy - - Social media content creation
social-content - - Growth tactics
marketing-ideas
- - 产品发布规划
launch-strategy - - 社交媒体内容创作
social-content - - 增长策略
marketing-ideas