-
Notifications
You must be signed in to change notification settings - Fork 30
feat: add new Vercel example #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
6b066ac
Update Vercel example
ldhenry 7546240
run prettier
ldhenry 2b65ecc
clenaup: move vercel into examples dir
ldhenry ac22b4a
Add complete example
ldhenry 80a7aba
merge main
ldhenry d8e6e54
Small cleanup
ldhenry b6eaf64
Small cleanup
ldhenry 963ec16
Add README to examples dir
ldhenry a30a927
Cleanup readme
ldhenry 92ac0d0
Delete eslint.json
ldhenry ed0635a
Re-add .eslintrc.json
ldhenry 31990e6
Ignore eslint in example dirs
ldhenry 1596592
Update README.md
ldhenry b10e01c
Address PR feedback
ldhenry File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't figure out how to get eslint to play nicely with the
eslintrc
file in the complete example so I decided to just ignore it here.