-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds a new Vercel example that showcases the following: 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` and `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`. I'm open to suggestions on new names for the examples.
- Loading branch information
Showing
44 changed files
with
661 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"root": true, | ||
"extends": "next/core-web-vitals" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
legacy-peer-deps=true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
export default function Closed() { | ||
return ( | ||
<div className="flex flex-col items-center min-h-[calc(100vh-44px)] justify-center bg-gray-100"> | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
preserveAspectRatio="xMidYMid" | ||
viewBox="0 0 256 315" | ||
className="w-16 h-16 text-black" | ||
> | ||
<path | ||
fill="currentColor" | ||
d="M213.803 167.03c.442 47.58 41.74 63.413 42.197 63.615-.35 1.116-6.599 22.563-21.757 44.716-13.104 19.153-26.705 38.235-48.13 38.63-21.05.388-27.82-12.483-51.888-12.483-24.061 0-31.582 12.088-51.51 12.871-20.68.783-36.428-20.71-49.64-39.793-27-39.033-47.633-110.3-19.928-158.406 13.763-23.89 38.36-39.017 65.056-39.405 20.307-.387 39.475 13.662 51.889 13.662 12.406 0 35.699-16.895 60.186-14.414 10.25.427 39.026 4.14 57.503 31.186-1.49.923-34.335 20.044-33.978 59.822M174.24 50.199c10.98-13.29 18.369-31.79 16.353-50.199-15.826.636-34.962 10.546-46.314 23.828-10.173 11.763-19.082 30.589-16.678 48.633 17.64 1.365 35.66-8.964 46.64-22.262" | ||
/> | ||
</svg> | ||
<h1 className="text-5xl tracking-tight max-w-3xl font-semibold mb-4 mt-10"> | ||
We'll be back. | ||
</h1> | ||
<p className="ml-4 text-gray-500 text-xl"> | ||
We're busy updating the Apple Store for you and will be back soon. | ||
</p> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 `<LaunchDarklyProvider>` component. | ||
const allFlags = (await ldEdgeClient.allFlagsState(context)).toJSON() as { | ||
'bootstrap-flags': boolean; | ||
}; | ||
const bootstrappedFlags = allFlags['bootstrap-flags'] ? allFlags : undefined; | ||
|
||
return ( | ||
<html lang="en"> | ||
<body> | ||
<LaunchDarklyProvider | ||
envId={process.env.LD_CLIENT_SIDE_ID || ''} | ||
context={context} | ||
bootstrappedFlags={bootstrappedFlags} | ||
> | ||
<Nav /> | ||
{children} | ||
</LaunchDarklyProvider> | ||
</body> | ||
</html> | ||
); | ||
} |
68 changes: 68 additions & 0 deletions
68
packages/sdk/vercel/examples/complete/app/missing-edge-config/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
export default function MissingEdgeConfigDialog() { | ||
return ( | ||
<div className="relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="true"> | ||
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" /> | ||
<div className="fixed inset-0 z-10 overflow-y-auto"> | ||
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0"> | ||
<div className="relative transform overflow-hidden rounded-lg bg-white px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6"> | ||
<div className="sm:flex sm:items-start"> | ||
<div className="mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-gray-100 sm:mx-0 sm:h-10 sm:w-10"> | ||
{/* Heroicon name: outline/exclamation-triangle */} | ||
<svg | ||
className="h-6 w-6 text-gray-600" | ||
xmlns="http://www.w3.org/2000/svg" | ||
fill="none" | ||
viewBox="0 0 24 24" | ||
strokeWidth="1.5" | ||
stroke="currentColor" | ||
aria-hidden="true" | ||
> | ||
<path | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
d="M12 10.5v3.75m-9.303 3.376C1.83 19.126 2.914 21 4.645 21h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 4.88c-.866-1.501-3.032-1.501-3.898 0L2.697 17.626zM12 17.25h.007v.008H12v-.008z" | ||
/> | ||
</svg> | ||
</div> | ||
<div className="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left"> | ||
<h3 className="text-lg font-medium leading-6 text-gray-900" id="modal-title"> | ||
Incomplete Environment Variables Setup | ||
</h3> | ||
<div className="mt-2"> | ||
<p className="text-sm text-gray-500"> | ||
Follow these steps to finish the setup of this example: | ||
</p> | ||
<ol className="text-sm text-gray-500 list-disc ml-8 mt-2 flex gap-2 flex-col"> | ||
<li className="list-item list-disc"> | ||
Create an Edge Config and connect it to this project and store its connection | ||
string under the{' '} | ||
<span className="bg-gray-100 p-1 text-gray-900 rounded">EDGE_CONFIG</span>{' '} | ||
environment variable | ||
</li> | ||
<li className="list-item list-disc"> | ||
Pull your latest Environment Variables if you are developing locally | ||
</li> | ||
<li className="list-item list-disc">Restart or redeploy your application</li> | ||
</ol> | ||
<p className="text-sm text-gray-500 mt-2"> | ||
Then reload the page and this dialog will go away if your setup is correct. | ||
</p> | ||
</div> | ||
</div> | ||
</div> | ||
<div className="mt-5 sm:mt-4 sm:ml-10 sm:flex sm:pl-4"> | ||
<a | ||
href="https://github.com/vercel/examples/blob/main/edge-middleware/feature-flag-apple-store/README.md#set-up-environment-variables" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
className="inline-flex w-full justify-center rounded-md border border-transparent bg-gray-600 px-4 py-2 text-base font-medium text-white shadow-sm hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 sm:w-auto sm:text-sm" | ||
> | ||
Open Documentation | ||
</a> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.