diff --git a/.eslintrc.js b/.eslintrc.js
index 38837c520..6dd1a6cc9 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,7 +8,7 @@ module.exports = {
project: './tsconfig.eslint.json',
},
plugins: ['@typescript-eslint', 'prettier'],
- ignorePatterns: ['**/dist/**'],
+ ignorePatterns: ['**/dist/**', '**/vercel/examples/**'],
rules: {
'prettier/prettier': ['error'],
'class-methods-use-this': 'off',
diff --git a/package.json b/package.json
index 440397482..419294818 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,8 @@
"packages/sdk/cloudflare",
"packages/sdk/cloudflare/example",
"packages/sdk/vercel",
- "packages/sdk/vercel/example-vercel",
+ "packages/sdk/vercel/examples/complete",
+ "packages/sdk/vercel/examples/route-handler",
"packages/sdk/akamai"
],
"private": true,
diff --git a/packages/sdk/vercel/README.md b/packages/sdk/vercel/README.md
index fa0785f37..a2ca6fbf7 100644
--- a/packages/sdk/vercel/README.md
+++ b/packages/sdk/vercel/README.md
@@ -6,9 +6,13 @@
[![NPM][sdk-vercel-dm-badge]][sdk-vercel-npm-link]
[![NPM][sdk-vercel-dt-badge]][sdk-vercel-npm-link]
-This library supports using Vercel [Edge Config](https://vercel.com/docs/concepts/edge-network/edge-config) to replace the default in-memory feature store of the [LaunchDarkly Node.js SDK](https://github.com/launchdarkly/vercel-server-sdk).
+This library supports using Vercel [Edge Config](https://vercel.com/docs/concepts/edge-network/edge-config) to replace the default in-memory feature store of the [LaunchDarkly Node.js SDK](https://github.com/launchdarkly/node-server-sdk).
-For more information, see the [SDK features guide](https://docs.launchdarkly.com/sdk/features/storing-data).
+## The LaunchDarkly Vercel integration is required
+
+This SDK requires [LaunchDarkly's Vercel integration](https://docs.launchdarkly.com/integrations/vercel?q=verc) to push feature flag data into a Vercel Edge Config. The Vercel integration is available to customers on an Enterprise plan. To learn more, [read about our pricing](https://launchdarkly.com/pricing/). To upgrade your plan, [contact Sales](https://launchdarkly.com/contact-sales/).
+
+For more information, see the [Vercel SDK reference](https://docs.launchdarkly.com/sdk/edge/vercel).
## Install
@@ -22,16 +26,16 @@ or yarn:
yarn add -D @launchdarkly/vercel-server-sdk
```
-## Quickstart
+## Quick start
-Initialize the ldClient with the [Vercel Edge SDK](https://vercel.com/docs/concepts/edge-network/edge-config/edge-config-sdk) and your LaunchDarkly client side sdk key:
+Initialize the ldClient with the [Vercel Edge SDK](https://vercel.com/docs/concepts/edge-network/edge-config/edge-config-sdk) and your LaunchDarkly [client-side ID](https://docs.launchdarkly.com/sdk/concepts/client-side-server-side#client-side-id):
```typescript
-import init from '@launchdarkly/vercel-server-sdk';
+import { init } from '@launchdarkly/vercel-server-sdk';
import { createClient } from '@vercel/edge-config';
const edgeClient = createClient(process.env.EDGE_CONFIG);
-const ldClient = init('YOUR CLIENT-SIDE SDK KEY', edgeClient);
+const ldClient = init('YOUR CLIENT-SIDE ID', edgeClient);
await ldClient.waitForInitialization();
const ldContext = {
@@ -42,7 +46,7 @@ const ldContext = {
const flagValue = await ldClient.variation('my-flag', ldContext, true);
```
-To learn more, head straight to the [complete reference guide for this SDK](https://docs.launchdarkly.com/sdk/server-side/vercel).
+To learn more, see the [examples](examples/README.md) in this repository or head straight to the [complete reference guide for this SDK](https://docs.launchdarkly.com/sdk/server-side/vercel).
## Developing this SDK
diff --git a/packages/sdk/vercel/examples/README.md b/packages/sdk/vercel/examples/README.md
new file mode 100644
index 000000000..6bef05a4a
--- /dev/null
+++ b/packages/sdk/vercel/examples/README.md
@@ -0,0 +1,19 @@
+# LaunchDarkly Vercel Edge SDK examples
+
+The following examples showcase using the LaunchDarkly Vercel Edge SDK to evaluate feature flags in Vercel's [Edge Runtime](https://vercel.com/docs/concepts/functions/edge-functions/edge-runtime). Both examples require the use of the [LaunchDarkly Vercel integration](https://docs.launchdarkly.com/integrations/vercel) to push feature flag data into Vercel's Edge Config.
+
+## [Complete example](complete/README.md)
+
+This example shows how to evaluate feature flags in Vercel's edge runtime using the [LaunchDarkly Vercel SDK](https://github.com/launchdarkly/js-core/tree/main/packages/sdk/vercel). Two primary use cases are highlighted:
+
+1. Bootstrapping feature flags from the edge runtime and consuming them in the [LaunchDarkly Client-side SDK for React](https://github.com/launchdarkly/react-client-sdk). This is leveraging feature flags in edge-rendered pages while still maintaining the events and ergonomics provided by the React SDK. You can see details in [`app/layout.tsx`](./app/layout.tsx) and [`components/launchdarklyProvider.tsx`](./components/launchdarklyProvider.tsx).
+2. Evaluating feature flags in the [Edge Middleware](https://vercel.com/docs/concepts/functions/edge-middleware). This can be seen in [`middleware.ts`](./middleware.ts).
+
+### Demo
+
+https://hello-vercel-edge.vercel.app/
+
+## [Route Handler example](route-handler/README.md)
+
+This is an example test app to showcase the usage of the Vercel LaunchDarkly
+SDK to evaluate a feature flag in a [Route Handler](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) using [Vercel's edge runtime](https://nextjs.org/docs/app/building-your-application/routing/router-handlers#edge-and-nodejs-runtimes).
diff --git a/packages/sdk/vercel/examples/complete/.eslintrc.json b/packages/sdk/vercel/examples/complete/.eslintrc.json
new file mode 100644
index 000000000..a2569c2c7
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/.eslintrc.json
@@ -0,0 +1,4 @@
+{
+ "root": true,
+ "extends": "next/core-web-vitals"
+}
diff --git a/packages/sdk/vercel/examples/complete/.gitignore b/packages/sdk/vercel/examples/complete/.gitignore
new file mode 100644
index 000000000..34d63f073
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/.gitignore
@@ -0,0 +1,43 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# Dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# Testing
+/coverage
+
+# Next.js
+/.next/
+/out/
+
+# VS code
+/.vscode
+
+# Production
+/build
+
+# Misc
+.DS_Store
+*.pem
+
+# Debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Local ENV files
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+# Vercel
+.vercel
+
+# Turborepo
+.turbo
+
+# typescript
+*.tsbuildinfo
\ No newline at end of file
diff --git a/packages/sdk/vercel/examples/complete/.npmrc b/packages/sdk/vercel/examples/complete/.npmrc
new file mode 100644
index 000000000..e9ee3cb4d
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/.npmrc
@@ -0,0 +1 @@
+legacy-peer-deps=true
\ No newline at end of file
diff --git a/packages/sdk/vercel/examples/complete/README.md b/packages/sdk/vercel/examples/complete/README.md
new file mode 100644
index 000000000..06a333c04
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/README.md
@@ -0,0 +1,58 @@
+# Complete example app for Vercel LaunchDarkly SDK
+
+This example shows how to evaluate feature flags in Vercel's edge runtime using the [LaunchDarkly Vercel SDK](https://github.com/launchdarkly/js-core/tree/main/packages/sdk/vercel). Two primary use cases are highlighted:
+
+1. Bootstrapping feature flags from the edge runtime and consuming them in the [LaunchDarkly Client-side SDK for React](https://github.com/launchdarkly/react-client-sdk). This is leveraging feature flags in edge-rendered pages while still maintaining the events and ergonomics provided by the React SDK. You can see details in [`app/layout.tsx`](./app/layout.tsx) and [`components/launchdarklyProvider.tsx`](./components/launchdarklyProvider.tsx).
+2. Evaluating feature flags in the [Edge Middleware](https://vercel.com/docs/concepts/functions/edge-middleware). This can be seen in [`middleware.ts`](./middleware.ts).
+
+## Demo
+
+https://hello-vercel-edge.vercel.app/
+
+## Local development
+
+#### Create a new LaunchDarkly project and flags
+
+For simplicity, we recommend [creating a new LaunchDarkly project](https://docs.launchdarkly.com/home/organize/projects/?q=create+proj) for this example app. After creating a new project, create the following feature flags with Client-side SDK availability:
+
+- `bootstrap-flags` - (Boolean) - This flag will determine whether or not the LaunchDarkly React SDK will bootstrap feature flags from the edge.
+- `show-debugging-info` - (Boolean) - This flag is used to expose the current flag values.
+- `hero-text` - (String) - This flag is used to dynamically change the hero text. You can make the variations anything you want, e.g. "The best way to buy the products you love."
+- `enable-hot-dog-favicon` - (Boolean) - This flag is used in middleware.ts to dynamically load a different favicon.
+- `store-closed` - (Boolean) - This flag is evaluated in `middleware.ts` and can be used to load a different home page when the store is closed.
+
+#### Set up the LaunchDarkly Vercel integration
+
+You will need to have the LaunchDarkly Vercel integration configured to push feature flag data to your Vercel Edge Config. Read the [Vercel documentation](https://docs.launchdarkly.com/integrations/vercel/) to set up the integration. Be sure to connect the project you created above.
+
+#### Set up environment variables
+
+1. Copy this directory in a new repository.
+2. Create a new Vercel project based on the new repository.
+3. [Add a new environment variable to your project](https://vercel.com/docs/concepts/projects/environment-variables) named `LD_CLIENT_SIDE_ID` and set it to the LaunchDarkly client-side ID for the **Test** environment in the project you created above.
+4. Follow [Vercel's documentation](https://vercel.com/docs/storage/edge-config/get-started) to connect an Edge Config to your new project.
+5. Run the following command to link your local codebase to your Vercel project:
+
+```shell
+vercel link
+```
+
+6. Run the following command to sync your projects environment variables in your development environment:
+
+```shell
+vercel env pull .env.development.local
+```
+
+7. After completing the guide above, you should have linked this example app to your Vercel project and created an `.env.development.local`.
+8. Verify the contents of `.env.development.local` have values for the `LD_CLIENT_SIDE_ID` and `EDGE_CONFIG`.
+9. Run the following command to install all dependencies:
+
+```shell
+yarn
+```
+
+10. Run the following command to start your development environment:
+
+```shell
+yarn dev
+```
diff --git a/packages/sdk/vercel/examples/complete/app/closed/page.tsx b/packages/sdk/vercel/examples/complete/app/closed/page.tsx
new file mode 100644
index 000000000..d8f6e833a
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/app/closed/page.tsx
@@ -0,0 +1,23 @@
+export default function Closed() {
+ return (
+
+
+
+ We'll be back.
+
+
+ We're busy updating the Apple Store for you and will be back soon.
+
+
+ );
+}
diff --git a/packages/sdk/vercel/examples/complete/app/layout.tsx b/packages/sdk/vercel/examples/complete/app/layout.tsx
new file mode 100644
index 000000000..613257dbf
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/app/layout.tsx
@@ -0,0 +1,48 @@
+import 'tailwindcss/tailwind.css';
+import Nav from 'components/nav';
+import { ReactElement } from 'react';
+import { headers } from 'next/headers';
+import { LDMultiKindContext } from '@launchdarkly/vercel-server-sdk';
+import LaunchDarklyProvider from 'components/launchdarklyProvider';
+import { ldEdgeClient } from 'lib/ldEdgeClient';
+
+// Specify the `edge` runtime to use the LaunchDarkly Edge SDK in layouts
+export const runtime = 'edge';
+
+export default async function RootLayout({ children }: { children: ReactElement }) {
+ const headersList = headers();
+ await ldEdgeClient.waitForInitialization();
+
+ // Here we are using basic information from the request as the LaunchDarkly context. If you have session auth in place,
+ // you will likely want to also include user and organization context.
+ const context: LDMultiKindContext = {
+ kind: 'multi',
+ user: { key: 'anonymous', anonymous: true },
+ 'user-agent': { key: headersList.get('user-agent') || 'unknown' },
+ method: {
+ key: 'GET',
+ },
+ };
+
+ // The allFlagsState call is used to evaluate all feature flags for a given context so they can be bootstrapped but the
+ // LaunchDarkly React SDK in the `` component.
+ const allFlags = (await ldEdgeClient.allFlagsState(context)).toJSON() as {
+ 'bootstrap-flags': boolean;
+ };
+ const bootstrappedFlags = allFlags['bootstrap-flags'] ? allFlags : undefined;
+
+ return (
+
+
+
+
+ {children}
+
+
+
+ );
+}
diff --git a/packages/sdk/vercel/examples/complete/app/missing-edge-config/page.tsx b/packages/sdk/vercel/examples/complete/app/missing-edge-config/page.tsx
new file mode 100644
index 000000000..695cadcf3
--- /dev/null
+++ b/packages/sdk/vercel/examples/complete/app/missing-edge-config/page.tsx
@@ -0,0 +1,68 @@
+export default function MissingEdgeConfigDialog() {
+ return (
+