From 1fd092465003deca1d286a21631af3984dcab54b Mon Sep 17 00:00:00 2001 From: Vincent Derks Date: Tue, 15 Sep 2026 14:35:03 +0200 Subject: [PATCH] docs(skills): fix flag cleanup and Next.js guidance --- skills/flags-sdk/SKILL.md | 16 ++-------------- skills/flags-sdk/references/nextjs.md | 21 ++++++--------------- skills/flags-sdk/references/providers.md | 6 ++++-- 3 files changed, 12 insertions(+), 31 deletions(-) diff --git a/skills/flags-sdk/SKILL.md b/skills/flags-sdk/SKILL.md index 0dc5c401..5884bb13 100644 --- a/skills/flags-sdk/SKILL.md +++ b/skills/flags-sdk/SKILL.md @@ -356,21 +356,9 @@ export const handle = createHandle({ secret: FLAGS_SECRET, flags }); ## FLAGS_SECRET -Required for precompute and Flags Explorer. Must be 32 random bytes, base64-encoded: +Required for precompute and Flags Explorer. Vercel Flags activation creates a value per environment. Preserve existing values; do not rotate them during ordinary SDK setup. A missing local value does not mean the remote value is missing: check the target environment first, then follow [Pull environment variables](#pull-environment-variables) for Development. -```sh -node -e "console.log(crypto.randomBytes(32).toString('base64url'))" -``` - -Use a separate `FLAGS_SECRET` value for each environment (Development, Preview, Production), and mark the Preview and Production values as Sensitive. Run the generator once per environment to produce distinct values, then store each on Vercel: - -```sh -vercel env add FLAGS_SECRET production --sensitive --value -vercel env add FLAGS_SECRET preview --sensitive --value -vercel env add FLAGS_SECRET development --value -``` - -Then run `vc env pull` to sync to local. +Only generate a secret for an environment where it is absent. Use 32 cryptographically random bytes, base64-encoded, with a distinct value per environment. Mark Preview and Production values Sensitive. Send generated values directly to storage, such as stdin for `vercel env add`; do not print them to terminal output, logs, or chat, or embed them in command arguments. ## Precompute pattern diff --git a/skills/flags-sdk/references/nextjs.md b/skills/flags-sdk/references/nextjs.md index 4c3f32f0..89cc33cd 100644 --- a/skills/flags-sdk/references/nextjs.md +++ b/skills/flags-sdk/references/nextjs.md @@ -177,19 +177,7 @@ Keep pages static while using feature flags. Proxy evaluates flags and encodes r ### Prerequisites -Set `FLAGS_SECRET` env var (32 random bytes, base64-encoded). Use a separate value for each environment (Development, Preview, Production), and mark the Preview and Production values as Sensitive. Run the generator once per environment to produce distinct values: - -```sh -node -e "console.log(crypto.randomBytes(32).toString('base64url'))" -``` - -Store each on Vercel: - -```sh -vercel env add FLAGS_SECRET production --sensitive --value -vercel env add FLAGS_SECRET preview --sensitive --value -vercel env add FLAGS_SECRET development --value -``` +Ensure `FLAGS_SECRET` is configured using [FLAGS_SECRET](../SKILL.md#flags_secret). Reuse existing values; generate one only for an environment where it is absent. ### Step 1: Create flag group @@ -431,8 +419,11 @@ export const getOrGenerateVisitorId = async ( ```ts const identify = dedupe( - async ({ cookies }: { cookies: ReadonlyRequestCookies }): Promise => { - const visitorId = await getOrGenerateVisitorId(cookies); + async ({ cookies, headers }: { + cookies: ReadonlyRequestCookies; + headers: ReadonlyHeaders; + }): Promise => { + const visitorId = await getOrGenerateVisitorId(cookies, headers); return { visitor: visitorId ? { id: visitorId } : undefined }; }, ); diff --git a/skills/flags-sdk/references/providers.md b/skills/flags-sdk/references/providers.md index a35756de..b3dadc5a 100644 --- a/skills/flags-sdk/references/providers.md +++ b/skills/flags-sdk/references/providers.md @@ -152,13 +152,15 @@ For the current subcommand list and options, run `vercel flags --help` or `verce #### Lifecycle and safety -The docs describe these flows end to end: [Roll out a feature](https://vercel.com/docs/flags/vercel-flags/cli/roll-out-feature), [Run an A/B test](https://vercel.com/docs/flags/vercel-flags/cli/run-ab-test), [Clean up after rollout](https://vercel.com/docs/flags/vercel-flags/cli/clean-up-after-rollout). Follow them; the notes below are the parts an agent gets wrong. +The docs describe these flows end to end: [Roll out a feature](https://vercel.com/docs/flags/vercel-flags/cli/roll-out-feature), [Run an A/B test](https://vercel.com/docs/flags/vercel-flags/cli/run-ab-test). For cleanup, follow the deployment and evaluation checks below before archiving. - **Promote**: deploy the code to preview, `enable` or `set` the flag in preview, verify on the preview URL, deploy to production, then change production (`enable`, `set`, `split`, or `rollout`). Each environment keeps its own configuration; preview stays on its current value until you change it. - **Serve vs define**: `enable` / `disable` work on boolean flags only. `set` changes the served variant for any kind. `update` adds, removes, or renames variants and does not change what is served. A variant can only be removed when no environment configuration or rule references it, including rules that are stored but not active ([Deleting a variant](https://vercel.com/docs/flags/vercel-flags/dashboard/feature-flag#deleting-a-variant)). - **Static value vs targeting**: `set` / `enable` / `disable` put the environment in static value mode; its split, rollout, and rules are preserved in the background. `use-targeting` switches back to targets and rules mode ([Switching between static and rules modes](https://vercel.com/docs/flags/vercel-flags/dashboard/feature-flag#switching-between-static-and-rules-modes)). Run `inspect` first so you know what the environment serves today. - **Confirm a change**: `inspect` for the served state, `versions` for the change history (the dashboard can restore any earlier configuration), `evaluations` to confirm traffic reaches the new variant or to check whether a flag is still evaluated before archiving ([Evaluation metrics](https://vercel.com/docs/flags/vercel-flags/evaluation-metrics)). Local development evaluates the Development environment configuration. -- **Archive before delete**: archive after the flag is no longer used in code. Search the code for the key and its camelCase name, remove the declaration and the conditionals, deploy to preview, then `archive`; `unarchive` restores it with configuration and history intact. `rm` requires an archived flag and is permanent ([Clean up after rollout](https://vercel.com/docs/flags/vercel-flags/cli/clean-up-after-rollout), [Archive](https://vercel.com/docs/flags/vercel-flags/dashboard/archive)). +- **Deploy removal first**: search for the flag key and its camelCase name, remove the declaration and conditionals, verify in preview, and complete the rollout to production and every other environment using the flag. A merged PR or preview deployment is not sufficient. Older deployments can still evaluate it through [Skew Protection](https://vercel.com/docs/skew-protection#configure-maximum-age): inspect the project's configured maximum age and account for longer-lived traffic, including crawler exceptions, rather than assuming a fixed 24 or 48 hours. +- **Verify no evaluations**: before archiving, use `vercel flags evaluations --since --json` with the explicit project/team target. Require no evaluations over an observation window after rollout that covers the applicable Skew Protection period. Check that the returned time range covers the window and the data is not truncated. Clients using `@vercel/flags-core` before 1.6.0 do not report evaluations, so verify reporting coverage; an empty result alone does not prove disuse ([Evaluation metrics](https://vercel.com/docs/flags/vercel-flags/evaluation-metrics)). If evaluations continue, reporting coverage is unknown, or the window has not elapsed, leave the flag active. +- **Archive before delete**: only after those checks pass, `archive` the flag. `unarchive` restores its configuration and history. Keep it archived through the agreed observation period before permanent deletion; `rm` requires an archived flag and cannot be undone ([Archive](https://vercel.com/docs/flags/vercel-flags/dashboard/archive)). - **Agent runs**: `archive`, `unarchive`, `rm`, and `update --remove-variant` prompt for confirmation. Pass `--yes` when the user has approved the action. CLI reference: https://vercel.com/docs/cli/flags