关于 feature-flags
用于在应用中端到端接入 PostHog 功能标志的开发技能,涵盖服务端评估、客户端钩子和本地覆盖。它会先检查项目现有配置,并在已有 PostHog 集成上扩展。
主要功能
- 01检查现有 PostHog 配置
- 02在服务端评估标志
- 03交互后使用客户端钩子
- 04在本地开发中覆盖标志
- 05指导在 PostHog 中创建标志
适用场景
- 01控制路由或页面内容且避免初始闪烁
- 02按用户标志控制 API 行为
- 03在本地测试标志变体
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tushaarmehtaa/ tushar-skills --skill feature-flags安装后在 Claude Code 中输入/feature-flags确认已加载。
详细介绍
端到端接入 PostHog 功能标记——服务端评估、客户端 Hook 和本地开发覆盖。先读取项目,再扩展现有的 PostHog 配置(如果有)。
两个会悄悄导致 PostHog 功能标记失效的问题
- 需要服务端行为时,却在客户端评估功能标记。
useFeatureFlagEnabled会在水合后于浏览器中运行。如果你用功能标记控制页面某个区域的显示或隐藏,该区域会先闪现,然后消失。对于首屏可见内容或会影响路由的内容,应在服务端评估功能标记。 - 服务端调用缺少
distinctId。 PostHog 的服务端 SDK 需要唯一的用户标识符来评估功能标记。使用"anonymous"这类占位符意味着所有未认证用户都会获得相同的功能标记变体——这不是逐步放量,而是固定值。
第 1 阶段:检测项目
cat package.json | grep -E "posthog"
grep -r "posthog" src/ app/ --include="*.ts" --include="*.tsx" -l 2>/dev/null | head -5
- 已安装
posthog-js且找到 Provider? → 已配置 PostHog 客户端。在此基础上添加服务端 SDK。 - 已安装
posthog-node? → 扩展现有配置,不要重新安装。 - 都没有? → 先使用 add-analytics 技能从头接入 PostHog,然后回到这里。
第 2 阶段:安装服务端 SDK
npm install posthog-node
添加到 .env.example(如果已运行 add-analytics 技能,则已设置):
NEXT_PUBLIC_POSTHOG_KEY=
POSTHOG_API_KEY= # same as POSTHOG_KEY — use for server-side calls
第 3 阶段:服务端功能标记客户端
创建用于服务端评估的单例:
// lib/posthog-server.ts
import { PostHog } from 'posthog-node';
let client: PostHog | null = null;
export function getPostHogServer(): PostHog {
if (!client) {
client = new PostHog(process.env.POSTHOG_API_KEY!, {
host: 'https://us.i.posthog.com',
flushAt: 1, // flush immediately in serverless
flushInterval: 0,
});
}
return client;
}
export async function isFeatureEnabled(
flagKey: string,
distinctId: string,
groups?: Record<string, string>
): Promise<boolean> {
const ph = getPostHogServer();
const result = await ph.isFeatureEnabled(flagKey, distinctId, { groups });
return result ?? false;
}
export async function getFeatureFlagVariant(
flagKey: string,
distinctId: string
): Promise<string | boolean | undefined> {
const ph = getPostHogServer();
return ph.getFeatureFlag(flagKey, distinctId);
}
第 4 阶段:服务端组件用法
在服务端组件和路由处理程序中评估功能标记——不会出现客户端闪烁:
// app/dashboard/page.tsx (Server Component)
import { isFeatureEnabled } from '@/lib/posthog-server';
import { getAuthUser } from '@/lib/auth';
export default async function DashboardPage() {
const user = await getAuthUser();
const showNewDashboard = user
? await isFeatureEnabled('new-dashboard', user.id)
: false;
return showNewDashboard ? <NewDashboard /> : <OldDashboard />;
}
// app/api/generate/route.ts (Route Handler)
import { isFeatureEnabled } from '@/lib/posthog-server';
export async function POST(req: Request) {
const user = await getAuthUser(req);
if (!user) return Response.json({ error: 'Unauthorized' }, { status: 401 });
const hasStreamingAccess = await isFeatureEnabled('streaming-responses', user.id);
if (hasStreamingAccess) {
return handleStreaming(req, user);
}
return handleNonStreaming(req, user);
}
第 5 阶段:客户端用法
对于用户交互后才会改变 UI 的功能标记(而非初始渲染时):
// components/feature-flagged-button.tsx
'use client';
import { useFeatureFlagEnabled } from 'posthog-js/react';
export function NewFeatureButton() {
const isEnabled = useFeatureFlagEnabled('new-export-feature');
// useFeatureFlagEnabled returns undefined while loading
if (isEnabled === undefined) return null;
if (!isEnabled) return null;
return <button>Export (New)</button>;
}
切勿对首屏可见内容使用客户端 Hook。 Hook 在首次渲染时会返回 undefined,导致布局偏移。对于页面加载时可见的任何内容,都应使用服务端方案。
第 6 阶段:本地开发覆盖
添加仅用于开发环境的功能标记覆盖机制,以便在本地测试两个变体,而无需操作 PostHog:
// lib/posthog-server.ts (add to existing file)
export async function isFeatureEnabled(
flagKey: string,
distinctId: string,
groups?: Record<string, string>
): Promise<boolean> {
// Local override for development
if (process.env.NODE_ENV === 'development') {
const override = process.env[`FLAG_${flagKey.toUpperCase().replace(/-/g, '_')}`];
if (override === 'true') return true;
if (override === 'false') return false;
}
const ph = getPostHogServer();
const result = await ph.isFeatureEnabled(flagKey, distinctId, { groups });
return result ?? false;
}
在 .env.local 中:
FLAG_NEW_DASHBOARD=true # force-enable new-dashboard flag locally
FLAG_STREAMING_RESPONSES=false # force-disable
第 7 阶段:在 PostHog 中创建功能标记
明确告知用户需要设置的内容。在 PostHog 控制面板中:
- 功能标记 → 新建功能标记
- 键:
new-dashboard(与代码中的值一致) - 放量:从 0% 开始,逐步增加到 10%、50%、100%
- 条件:可按用户属性(plan = 'pro')、群组或百分比进行定向
对于 A/B 测试:使用“多个变体”而不是布尔值。然后使用 getFeatureFlagVariant() 并返回 'control' 或 'test'。
验证
[ ] posthog-node installed
[ ] POSTHOG_API_KEY in .env.example
[ ] Server-side evaluation uses real user ID as distinctId — not "anonymous"
[ ] Server Components use isFeatureEnabled() — not the client hook
[ ] Client hook used only for post-hydration interactions, not initial render
[ ] Local override via FLAG_* env vars works in development
[ ] Flags created in PostHog dashboard with matching key names
[ ] Test: set FLAG_[KEY]=false in .env.local — confirm feature is hidden
[ ] Test: set FLAG_[KEY]=true in .env.local — confirm feature is shown
[ ] PostHog flag set to 0% rollout first — expand after confirming it works
评论
支持 Markdown