From ff437da5723083afd2affe83be9a42fa917a4a2b Mon Sep 17 00:00:00 2001 From: Dominik Ferber Date: Tue, 17 Dec 2024 16:25:23 +0200 Subject: [PATCH] redo landing page --- .../getting-started/overview/[code]/flags.ts | 11 +++ .../overview/[code]/middleware.ts | 13 ++++ .../getting-started/overview/[code]/page.tsx | 72 +++++++++++++++++++ .../overview/[code]/reload-button.tsx | 20 ++++++ examples/docs/app/nav-items.ts | 2 + examples/docs/app/page.tsx | 39 ---------- examples/docs/app/philosophy/page.tsx | 18 +++-- examples/docs/middleware.ts | 6 ++ 8 files changed, 136 insertions(+), 45 deletions(-) create mode 100644 examples/docs/app/getting-started/overview/[code]/flags.ts create mode 100644 examples/docs/app/getting-started/overview/[code]/middleware.ts create mode 100644 examples/docs/app/getting-started/overview/[code]/page.tsx create mode 100644 examples/docs/app/getting-started/overview/[code]/reload-button.tsx delete mode 100644 examples/docs/app/page.tsx diff --git a/examples/docs/app/getting-started/overview/[code]/flags.ts b/examples/docs/app/getting-started/overview/[code]/flags.ts new file mode 100644 index 0000000..423911b --- /dev/null +++ b/examples/docs/app/getting-started/overview/[code]/flags.ts @@ -0,0 +1,11 @@ +import { flag } from '@vercel/flags/next'; + +export const randomFlag = flag({ + key: 'random-flag', + description: 'A flag that is on for 50% of visitors', + decide() { + return Math.random() > 0.5; + }, +}); + +export const overviewFlags = [randomFlag]; diff --git a/examples/docs/app/getting-started/overview/[code]/middleware.ts b/examples/docs/app/getting-started/overview/[code]/middleware.ts new file mode 100644 index 0000000..128677b --- /dev/null +++ b/examples/docs/app/getting-started/overview/[code]/middleware.ts @@ -0,0 +1,13 @@ +import { precompute } from '@vercel/flags/next'; +import { type NextRequest, NextResponse } from 'next/server'; +import { overviewFlags } from './flags'; + +export async function overviewMiddleware(request: NextRequest) { + // precompute the flags + const code = await precompute(overviewFlags); + + // rewrite the page with the code + return NextResponse.rewrite( + new URL(`/getting-started/overview/${code}`, request.url), + ); +} diff --git a/examples/docs/app/getting-started/overview/[code]/page.tsx b/examples/docs/app/getting-started/overview/[code]/page.tsx new file mode 100644 index 0000000..562200b --- /dev/null +++ b/examples/docs/app/getting-started/overview/[code]/page.tsx @@ -0,0 +1,72 @@ +import { Content } from '@/components/content'; +import { DemoFlag } from '@/components/demo-flag'; +import { randomFlag, overviewFlags } from './flags'; +import { ReloadButton } from './reload-button'; +import { CodeBlock } from '@/components/code-block'; +import Link from 'next/link'; + +export const dynamic = 'error'; + +export default async function Page({ + params, +}: { + params: Promise<{ code: string }>; +}) { + const awaitedParams = await params; + const overview = await randomFlag(awaitedParams.code, overviewFlags); + return ( + +

Overview

+

The Flags SDK makes it easy to use feature flags in Next.js.

+
    +
  • Works with any flag provider, with built-in adapters for many
  • +
  • App Router, Pages Router and Edge Middleware compatible
  • +
  • Supports dynamic and static pages
  • +
  • Implements best practices to avoid common pitfalls
  • +
+

Usage example

+

+ Declare a new feature flag using the flag function. +

+ + {` + import { flag } from '@vercel/flags/next'; + + export const randomFlag = flag({ + key: "random-flag", + decide() { + // this flag will be on for 50% of visitors + return Math.random() > 0.5; + } + });`} + +

Use the flag by calling it like any other async function.

+ {`await randomFlag()`} +

This demo flag is on for 50% of visitors.

+ + +

+ See the Quickstart for + full setup instructions. +

+

Introduction

+

+ This package provides a simple way to use feature flags in your Next.js + applications. It can be used no matter if your application is hosted on + Vercel or not. It works with App Router, Pages Router and Edge + Middleware. It also works with any feature flag provider. +

+

+ This package encodes the best practices when using feature flags in + Next.js. We also understand that you sometimes need to deviate from the + golden path, and have examples for those cases as well. +

+

+ While this package is called @vercel/flags it does not + require using Vercel. It is also not limited to feature flags, and can + be used for experimentation, A/B testing and any other dynamic flagging + of code. +

+
+ ); +} diff --git a/examples/docs/app/getting-started/overview/[code]/reload-button.tsx b/examples/docs/app/getting-started/overview/[code]/reload-button.tsx new file mode 100644 index 0000000..acb46b8 --- /dev/null +++ b/examples/docs/app/getting-started/overview/[code]/reload-button.tsx @@ -0,0 +1,20 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { useRouter } from 'next/navigation'; + +export function ReloadButton() { + const router = useRouter(); + + return ( + + ); +} diff --git a/examples/docs/app/nav-items.ts b/examples/docs/app/nav-items.ts index 5514fd5..7e9037b 100644 --- a/examples/docs/app/nav-items.ts +++ b/examples/docs/app/nav-items.ts @@ -33,11 +33,13 @@ export const navItems: Item[] = [ title: 'Why Feature Flags?', slug: 'why-feature-flags', url: '/philosophy/why-feature-flags', + nav: 'hidden', }, { title: 'Why Experimentation?', slug: 'why-experimentation', url: '/philosophy/why-experimentation', + nav: 'hidden', }, { title: 'Flags as Code', diff --git a/examples/docs/app/page.tsx b/examples/docs/app/page.tsx deleted file mode 100644 index 4518357..0000000 --- a/examples/docs/app/page.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Content } from '@/components/content'; - -export default function Page() { - return ( - -

Overview

-

The feature flags SDK by Vercel for Next.js.

-

- This package provides a simple way to use feature flags in your Next.js - applications. It can be used no matter if your application is hosted on - Vercel or not. It works with App Router, Pages Router and Edge - Middleware. It also works with any feature flag provider. -

-

- This package encodes the best practices when using feature flags in - Next.js. We also understand that you sometimes need to deviate from the - golden path, and have examples for those cases as well. -

-

- While this package is called @vercel/flags it does not - require using Vercel. It is also not limited to feature flags, and can - be used for experimentation, A/B testing and any other dynamic flagging - of code. -

-

Rendering strategies

-

- In Next.js, there are several ways to render a page. This SDK works with - all of them, no matter if you are using server-side rendering, static - site generation, partial prerendering or Edge Middleware. -

-

Feature Flag Providers

-

- The Flags SDK works with any feature flag provider. We offer adapters - for commonly used providers, but it is also possible to write a custom - adapter in case you have an in-house solution for feature flags. -

-
- ); -} diff --git a/examples/docs/app/philosophy/page.tsx b/examples/docs/app/philosophy/page.tsx index 704fa1d..5018ecf 100644 --- a/examples/docs/app/philosophy/page.tsx +++ b/examples/docs/app/philosophy/page.tsx @@ -1,18 +1,24 @@ import { Content } from '@/components/content'; +import Link from 'next/link'; export default function Page() { return (

Philosophy

- We believe the best way to use feature flags is to use them server-side. - Using feature flags server-side prevents common problems that come with - client-side usage, like layout shift or flashing the wrong content. + The Flags SDK encodes best practices and opinionated patterns around + flag usage.

+

At a glance, the philosophy is:

+
    +
  • flags are always used server-side
  • +
  • flags do not accept arguments on the call-side
  • +
  • flags declare their evaluation context
  • +
  • flags delcare their default value
  • +

- This approach fits extremely well with the App Router in Next.js. With - React Server Components, there is always a way to load feature flags on - the server. + Read more about this philosophy in the{' '} + Flags as Code section.

); diff --git a/examples/docs/middleware.ts b/examples/docs/middleware.ts index 0238b89..dd49b13 100644 --- a/examples/docs/middleware.ts +++ b/examples/docs/middleware.ts @@ -1,9 +1,14 @@ import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; import { marketingMiddleware } from './app/examples/marketing-pages/middleware'; +import { overviewMiddleware } from './app/getting-started/overview/[code]/middleware'; import { featureFlagsInEdgeMiddleware } from './app/examples/feature-flags-in-edge-middleware/middleware'; export function middleware(request: NextRequest) { + if (request.nextUrl.pathname === '/') { + return overviewMiddleware(request); + } + if (request.nextUrl.pathname === '/examples/marketing-pages') { return marketingMiddleware(request); } @@ -19,6 +24,7 @@ export function middleware(request: NextRequest) { export const config = { matcher: [ + '/', '/examples/marketing-pages', '/examples/feature-flags-in-edge-middleware', ],