Skip to content

Commit

Permalink
Add links to interactive examples (#87)
Browse files Browse the repository at this point in the history
* Add links to interactive examples
* improve example
  • Loading branch information
Tymek authored Oct 16, 2024
1 parent 9c8e5fb commit e0c3a64
Show file tree
Hide file tree
Showing 13 changed files with 39 additions and 35 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ yarn add @unleash/nextjs
pnpm add @unleash/nextjs
```

There is an [`./example`](./example) project that you can [deploy to Vercel](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FUnleash%2Funleash-client-nextjs%2Ftree%2Fmain%2Fexample) or [edit in CodeSandbox](https://codesandbox.io/s/github/Unleash/unleash-client-nextjs/tree/main/example).

### Environment variables

This package will attempt to load configuration from
Expand Down
6 changes: 3 additions & 3 deletions example/.env
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
NEXT_PUBLIC_UNLEASH_SERVER_API_URL=https://app.unleash-hosted.com/demo/api
# or: UNLEASH_SERVER_URL=https://app.unleash-hosted.com/demo/api

UNLEASH_SERVER_API_TOKEN=test-server:default.8a090f30679be7254af997864d66b86e44dcfc5291916adff72a0fb5
UNLEASH_SERVER_API_TOKEN=demo-app:dev.9fc74dd72d2b88bea5253c04240b21a54841f08d9918046ed55a06b5

# NEXT_PUBLIC_UNLEASH_FRONTEND_URL=https://app.unleash-hosted.com/demo/api/frontend
# or: UNLEASH_FRONTEND_URL=https://app.unleash-hosted.com/demo/api/frontend

NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN=default:default.26d592049f821f731f94047e7d760252f431697e2153b26f7eaba014
# or: UNLEASH_FRONTEND_API_TOKEN=demo-app:default.a901bd337765b46cfcf80d630c4c550e84845e840569b8f61e4c497d
NEXT_PUBLIC_UNLEASH_FRONTEND_API_TOKEN=demo-app:dev.95ae66ab673bf467facb68b2487904f4891064d26b47e89ca498063d
# or: UNLEASH_FRONTEND_API_TOKEN=demo-app:dev.95ae66ab673bf467facb68b2487904f4891064d26b47e89ca498063d

NEXT_PUBLIC_UNLEASH_APP_NAME=nextjs-example
# or: UNLAESH_APP_NAME=nextjs-example
Expand Down
23 changes: 13 additions & 10 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## Next.js with Unleash

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FUnleash%2Funleash-client-nextjs%2Ftree%2Fmain%2Fexample)
[![Edit in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/Unleash/unleash-client-nextjs/tree/main/example)

To run this code locally:

```bash
Expand All @@ -11,30 +14,30 @@ pnpm dev

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

Flag in use is `nextjs-example`. https://app.unleash-hosted.com/demo/projects/default/features/nextjs-example
Flag in use is `example-flag`. https://app.unleash-hosted.com/demo/projects/codesandbox/features/example-flag

## Available examples

### App Router

- `./src/app/app-page/page.tsx` - Server-side component page, with loader
- `./src/app/api-route/route.tsx` - JSON API response
- [`./src/app/page.tsx`](./src/app/page.tsx) - Server-side component page, with loader
- [`./src/app/api-route/route.ts`](./src/app/api-route/route.ts) - JSON API response

### Pages Router

- `./src/pages/csr.tsx` - Client-side rendering - simple use case, with loader
- `./src/pages/ssr.tsx` - Server-side rendering - when you need to keep some data private
- `./src/pages/ssg.tsx` - Static site generation - performance optimization
- [`./src/pages/csr.tsx`](./src/pages/csr.tsx) - Client-side rendering - simple use case, with loader
- [`./src/pages/ssr.tsx`](./src/pages/ssr.tsx) - Server-side rendering - when you need to keep some data private
- [`./src/pages/ssg.tsx`](./src/pages/ssg.tsx) - Static site generation - performance optimization

### API

- `./src/pages/api/hello.ts` - API route responding with JSON
- [`./src/pages/api/hello.ts`](./src/pages/api/hello.ts) - API route responding with JSON

### Middleware

Example of A/B testing with Next.js Middleware.
Redirect users to a different (pre-rendered) page based on a feature flag.

- `./src/pages/api/proxy-definitions.ts` - act as cache for feature flag definitions. This lets this SDK act as a substitute for Unleash Edge or the Unleash proxy that you can deploy on Next.js Edge.
- `./src/middleware.ts`- handle flag evaluation and transparently redirect to one of the pages in `./src/pages/ab` directory
- `./src/pages/ab/a` & `./src/pages/ab/b` - target pages. Both will be served at the URL `/ab`, but which one you see is decided by the feature flag in `./src/middleware.ts`.
- [`./src/pages/api/proxy-definitions.ts`](./src/pages/api/proxy-definitions.ts) - act as cache for feature flag definitions. This lets this SDK act as a substitute for Unleash Edge or the Unleash proxy that you can deploy on Next.js Edge.
- [`./src/middleware.ts`](./src/middleware.ts) - handle flag evaluation and transparently redirect to one of the pages in `./src/pages/ab` directory
- [`./src/pages/ab/a`](./src/pages/ab/a.tsx) & [`./src/pages/ab/b`](./src/pages/ab/b.tsx) - target pages. Both will be served at the URL `/ab`, but which one you see is decided by the feature flag in `./src/middleware.ts`.
13 changes: 6 additions & 7 deletions example/src/app/api-route/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,19 @@ import {
import type { NextRequest } from "next/server";
export const runtime = "edge";
export const preferredRegion = "fra1";

const COOKIE_NAME = "unleash-session-id";
import { UNLEASH_COOKIE_NAME } from "../../utils";

export async function GET(request: NextRequest) {
const sessionId =
request.cookies.get(COOKIE_NAME)?.value ||
request.cookies.get(UNLEASH_COOKIE_NAME)?.value ||
`${Math.floor(Math.random() * 1_000_000_000)}`;

const headers = {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Set-Cookie": `${COOKIE_NAME}=${sessionId}`,
"Set-Cookie": `${UNLEASH_COOKIE_NAME}=${sessionId}`,
};

try {
Expand All @@ -32,9 +31,9 @@ export async function GET(request: NextRequest) {
JSON.stringify({
activeToggles: toggles.length,
exampleToggle: {
url: "https://app.unleash-hosted.com/demo/projects/default/features/nextjs-example",
isEnabled: flags.isEnabled("nextjs-example"),
variant: flags.getVariant("nextjs-example"),
url: "https://app.unleash-hosted.com/demo/projects/codesandbox/features/example-flag",
isEnabled: flags.isEnabled("example-flag"),
variant: flags.getVariant("example-flag"),
},
}),
{
Expand Down
4 changes: 2 additions & 2 deletions example/src/app/client-page/_ClientComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useFlag, useFlagsStatus, useVariant } from "@unleash/nextjs/client";
import { LoadingDots } from "@vercel/examples-ui";

export default function ClientComponent() {
const isEnabled = useFlag("nextjs-example");
const variant = useVariant("nextjs-example");
const isEnabled = useFlag("example-flag");
const variant = useVariant("example-flag");
const { flagsReady } = useFlagsStatus();

if (!flagsReady) {
Expand Down
2 changes: 1 addition & 1 deletion example/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function Layout({ children }: { children: ReactNode }) {
return (
<html lang="en">
<body>
<Page>{children}</Page>
<Page className="p-6">{children}</Page>
</body>
</html>
);
Expand Down
6 changes: 3 additions & 3 deletions example/src/app/server-page-advanced/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const getData = async () => {
const flags = flagsClient(toggles);

return {
isEnabled: flags.isEnabled("nextjs-example"),
isEnabled: flags.isEnabled("example-flag"),
count: definitions?.features?.length || 0,
sessionId,
};
Expand All @@ -51,7 +51,7 @@ export default async function Page() {

// 'flag' function from SDK is configurable
const { variant } = await flag(
"nextjs-example",
"example-flag",
{
sessionId: cookies().get(COOKIE_NAME)?.value || "0", // context
},
Expand All @@ -66,7 +66,7 @@ export default async function Page() {
</Text>
<p>This page is server-side rendered.</p>
<p>
Feature flag <code>nextjs-example</code> is{" "}
Feature flag <code>example-flag</code> is{" "}
<strong>
<code>{isEnabled ? "ENABLED" : "DISABLED"}</code>
</strong>
Expand Down
4 changes: 2 additions & 2 deletions example/src/app/server-page/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Text } from "@vercel/examples-ui";
export const runtime = "edge";

export default async function Page() {
const { enabled } = await flag("nextjs-example");
const { enabled } = await flag("example-flag");

return (
<>
Expand All @@ -13,7 +13,7 @@ export default async function Page() {
</Text>
<p>This page is server-side rendered.</p>
<p>
Feature flag <code>nextjs-example</code> is{" "}
Feature flag <code>example-flag</code> is{" "}
<strong>
<code>{enabled ? "ENABLED" : "DISABLED"}</code>
</strong>
Expand Down
2 changes: 1 addition & 1 deletion example/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function middleware(req: NextRequest) {

// Evaluate based on provided context
const evaluated = evaluateFlags(definitions, context);
const variant = flagsClient(evaluated.toggles).getVariant("nextjs-example")
const variant = flagsClient(evaluated.toggles).getVariant("example-flag")
?.payload?.value;

const newUrl = req.nextUrl.clone();
Expand Down
2 changes: 1 addition & 1 deletion example/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "@vercel/examples-ui/globals.css";

export default function MyApp({ Component, pageProps }: AppProps) {
return (
<Page>
<Page className="p-6">
<Component {...pageProps} />
</Page>
);
Expand Down
2 changes: 1 addition & 1 deletion example/src/pages/csr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { LoadingDots } from "@vercel/examples-ui";
import type { NextPage } from "next";

const ExampleComponent = () => {
const isEnabled = useFlag("nextjs-example");
const isEnabled = useFlag("example-flag");
const { flagsReady } = useFlagsStatus();

if (!flagsReady) {
Expand Down
4 changes: 2 additions & 2 deletions example/src/pages/ssg.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export const getStaticProps: GetStaticProps<Data> = async (_ctx) => {

return {
props: {
isEnabled: flags.isEnabled("nextjs-example"),
variant: flags.getVariant("nextjs-example"),
isEnabled: flags.isEnabled("example-flag"),
variant: flags.getVariant("example-flag"),
},
};
};
Expand Down
4 changes: 2 additions & 2 deletions example/src/pages/ssr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export const getServerSideProps: GetServerSideProps<Data> = async (ctx) => {

return {
props: {
isEnabled: flags.isEnabled("nextjs-example"),
variant: flags.getVariant("nextjs-example"),
isEnabled: flags.isEnabled("example-flag"),
variant: flags.getVariant("example-flag"),
percent: Math.round((toggles.length / definitions.features.length) * 100),
},
};
Expand Down

0 comments on commit e0c3a64

Please sign in to comment.