From f60cb22f11299980fd2feaca22b6651840b131a8 Mon Sep 17 00:00:00 2001
From: David Nguyen
Date: Fri, 18 Aug 2023 20:05:14 +1000
Subject: [PATCH 1/3] feat: feature flags
---
.env.example | 7 +-
apps/web/package.json | 2 +
apps/web/process-env.d.ts | 2 -
.../app/(dashboard)/settings/billing/page.tsx | 6 +-
apps/web/src/app/layout.tsx | 31 +++--
.../(dashboard)/layout/profile-dropdown.tsx | 13 +-
.../settings/layout/desktop-nav.tsx | 9 +-
.../settings/layout/mobile-nav.tsx | 9 +-
.../forms/edit-document/add-fields.tsx | 2 +-
...entRect.ts => get-bounding-client-rect.ts} | 0
apps/web/src/helpers/get-feature-flag.ts | 79 ++++++++++++
.../src/helpers/get-post-hog-server-client.ts | 16 +++
.../get-server-component-feature-flag.ts | 26 ++++
apps/web/src/hooks/use-field-page-coords.ts | 2 +-
apps/web/src/pages/api/feature-flag/all.ts | 44 +++++++
apps/web/src/pages/api/feature-flag/get.ts | 122 ++++++++++++++++++
apps/web/src/providers/feature-flag.tsx | 96 ++++++++++++++
apps/web/src/providers/posthog.tsx | 52 ++++++++
package-lock.json | 116 +++++++++++++++++
packages/lib/constants/feature-flags.ts | 37 ++++++
packages/lib/constants/features.ts | 5 -
packages/tsconfig/process-env.d.ts | 2 -
turbo.json | 19 ++-
23 files changed, 661 insertions(+), 36 deletions(-)
rename apps/web/src/helpers/{getBoundingClientRect.ts => get-bounding-client-rect.ts} (100%)
create mode 100644 apps/web/src/helpers/get-feature-flag.ts
create mode 100644 apps/web/src/helpers/get-post-hog-server-client.ts
create mode 100644 apps/web/src/helpers/get-server-component-feature-flag.ts
create mode 100644 apps/web/src/pages/api/feature-flag/all.ts
create mode 100644 apps/web/src/pages/api/feature-flag/get.ts
create mode 100644 apps/web/src/providers/feature-flag.tsx
create mode 100644 apps/web/src/providers/posthog.tsx
create mode 100644 packages/lib/constants/feature-flags.ts
delete mode 100644 packages/lib/constants/features.ts
diff --git a/.env.example b/.env.example
index 47dea109e..afeb90343 100644
--- a/.env.example
+++ b/.env.example
@@ -52,7 +52,12 @@ NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID=
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_YEARLY_PRICE_ID=
# [[FEATURES]]
-NEXT_PUBLIC_SUBSCRIPTIONS_ENABLED=false
+# OPTIONAL: Leave blank to disable PostHog and feature flags.
+NEXT_PUBLIC_POSTHOG_KEY=""
+# OPTIONAL: Defines the host to use for PostHog.
+NEXT_PUBLIC_POSTHOG_HOST="https://eu.posthog.com"
+# OPTIONAL: Leave blank to disable billing.
+NEXT_PUBLIC_FEATURE_BILLING_ENABLED=
# This is only required for the marketing site
# [[REDIS]]
diff --git a/apps/web/package.json b/apps/web/package.json
index 31e8ff4f1..94c6e61af 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -27,6 +27,8 @@
"next-plausible": "^3.10.1",
"next-themes": "^0.2.1",
"perfect-freehand": "^1.2.0",
+ "posthog-js": "^1.75.3",
+ "posthog-node": "^3.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-dropzone": "^14.2.3",
diff --git a/apps/web/process-env.d.ts b/apps/web/process-env.d.ts
index e91137fe1..1cb0018ac 100644
--- a/apps/web/process-env.d.ts
+++ b/apps/web/process-env.d.ts
@@ -10,8 +10,6 @@ declare namespace NodeJS {
NEXT_PRIVATE_STRIPE_API_KEY: string;
NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET: string;
- NEXT_PUBLIC_SUBSCRIPTIONS_ENABLED: string;
-
NEXT_PRIVATE_GOOGLE_CLIENT_ID: string;
NEXT_PRIVATE_GOOGLE_CLIENT_SECRET: string;
}
diff --git a/apps/web/src/app/(dashboard)/settings/billing/page.tsx b/apps/web/src/app/(dashboard)/settings/billing/page.tsx
index 76d9df688..8773f1aa8 100644
--- a/apps/web/src/app/(dashboard)/settings/billing/page.tsx
+++ b/apps/web/src/app/(dashboard)/settings/billing/page.tsx
@@ -1,15 +1,17 @@
import { redirect } from 'next/navigation';
-import { IS_SUBSCRIPTIONS_ENABLED } from '@documenso/lib/constants/features';
import { getRequiredServerComponentSession } from '@documenso/lib/next-auth/get-server-session';
import { PasswordForm } from '~/components/forms/password';
+import { getServerComponentFlag } from '~/helpers/get-server-component-feature-flag';
export default async function BillingSettingsPage() {
const user = await getRequiredServerComponentSession();
+ const isBillingEnabled = await getServerComponentFlag('billing');
+
// Redirect if subscriptions are not enabled.
- if (!IS_SUBSCRIPTIONS_ENABLED) {
+ if (!isBillingEnabled) {
redirect('/settings/profile');
}
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 5bf2b9403..1d1e056ae 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -1,3 +1,5 @@
+import { Suspense } from 'react';
+
import { Caveat, Inter } from 'next/font/google';
import { TrpcProvider } from '@documenso/trpc/react';
@@ -5,8 +7,11 @@ import { cn } from '@documenso/ui/lib/utils';
import { Toaster } from '@documenso/ui/primitives/toaster';
import { TooltipProvider } from '@documenso/ui/primitives/tooltip';
+import { getServerComponentAllFlags } from '~/helpers/get-server-component-feature-flag';
+import { FeatureFlagProvider } from '~/providers/feature-flag';
import { ThemeProvider } from '~/providers/next-theme';
import { PlausibleProvider } from '~/providers/plausible';
+import { PostHogPageview } from '~/providers/posthog';
import './globals.css';
@@ -37,7 +42,9 @@ export const metadata = {
},
};
-export default function RootLayout({ children }: { children: React.ReactNode }) {
+export default async function RootLayout({ children }: { children: React.ReactNode }) {
+ const flags = await getServerComponentAllFlags();
+
return (
+
+
+
+
-
-
-
- {children}
-
-
-
-
+
+
+
+
+ {children}
+
+
+
+
+