diff --git a/app/(marketing)/page.tsx b/app/(marketing)/page.tsx index 9b321bd..cb01b6d 100644 --- a/app/(marketing)/page.tsx +++ b/app/(marketing)/page.tsx @@ -1,19 +1,24 @@ import Link from "next/link" -import { env } from "@/env.mjs" +import { env, isEnvVarSet } from "@/env.mjs" import { siteConfig } from "@/config/site" import { cn } from "@/lib/utils" import { buttonVariants } from "@/components/ui/button" async function getGitHubStars(): Promise { try { + const headers: Record = { + Accept: "application/vnd.github+json", + } + + if (isEnvVarSet("GITHUB_ACCESS_TOKEN")) { + headers.Authorization = `Bearer ${env.GITHUB_ACCESS_TOKEN}` + } + const response = await fetch( "https://api.github.com/repos/shadcn/taxonomy", { - headers: { - Accept: "application/vnd.github+json", - Authorization: `Bearer ${env.GITHUB_ACCESS_TOKEN}`, - }, + headers, next: { revalidate: 60, }, diff --git a/config/subscriptions.ts b/config/subscriptions.ts index 235a95a..813e73f 100644 --- a/config/subscriptions.ts +++ b/config/subscriptions.ts @@ -1,5 +1,5 @@ import { SubscriptionPlan } from "types" -import { env } from "@/env.mjs" +import { env, isEnvVarSet } from "@/env.mjs" export const freePlan: SubscriptionPlan = { name: "Free", @@ -11,5 +11,7 @@ export const freePlan: SubscriptionPlan = { export const proPlan: SubscriptionPlan = { name: "PRO", description: "The PRO plan has unlimited posts.", - stripePriceId: env.STRIPE_PRO_MONTHLY_PLAN_ID || "", + stripePriceId: isEnvVarSet("STRIPE_PRO_MONTHLY_PLAN_ID") + ? env.STRIPE_PRO_MONTHLY_PLAN_ID + : "", } diff --git a/env.mjs b/env.mjs index b3e960a..2d242ff 100644 --- a/env.mjs +++ b/env.mjs @@ -1,6 +1,54 @@ import { createEnv } from "@t3-oss/env-nextjs" import { z } from "zod" +const fallbackAppUrl = process.env.VERCEL_URL + ? `https://${process.env.VERCEL_URL}` + : "http://localhost:3000" + +const fallbackEnv = { + NEXTAUTH_URL: fallbackAppUrl, + NEXTAUTH_SECRET: "development-secret", + GITHUB_CLIENT_ID: "github-client-id-placeholder", + GITHUB_CLIENT_SECRET: "github-client-secret-placeholder", + GITHUB_ACCESS_TOKEN: "github-access-token-placeholder", + DATABASE_URL: "mysql://root:root@localhost:3306/taxonomy?schema=public", + SMTP_FROM: "notifications@example.com", + POSTMARK_API_TOKEN: "postmark-api-token-placeholder", + POSTMARK_SIGN_IN_TEMPLATE: "0", + POSTMARK_ACTIVATION_TEMPLATE: "0", + STRIPE_API_KEY: "sk_test_placeholder", + STRIPE_WEBHOOK_SECRET: "whsec_placeholder", + STRIPE_PRO_MONTHLY_PLAN_ID: "price_placeholder", + NEXT_PUBLIC_APP_URL: fallbackAppUrl, +} + +const runtimeEnv = { + NEXTAUTH_URL: process.env.NEXTAUTH_URL ?? fallbackEnv.NEXTAUTH_URL, + NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET ?? fallbackEnv.NEXTAUTH_SECRET, + GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID ?? fallbackEnv.GITHUB_CLIENT_ID, + GITHUB_CLIENT_SECRET: + process.env.GITHUB_CLIENT_SECRET ?? fallbackEnv.GITHUB_CLIENT_SECRET, + GITHUB_ACCESS_TOKEN: + process.env.GITHUB_ACCESS_TOKEN ?? fallbackEnv.GITHUB_ACCESS_TOKEN, + DATABASE_URL: process.env.DATABASE_URL ?? fallbackEnv.DATABASE_URL, + SMTP_FROM: process.env.SMTP_FROM ?? fallbackEnv.SMTP_FROM, + POSTMARK_API_TOKEN: + process.env.POSTMARK_API_TOKEN ?? fallbackEnv.POSTMARK_API_TOKEN, + POSTMARK_SIGN_IN_TEMPLATE: + process.env.POSTMARK_SIGN_IN_TEMPLATE ?? fallbackEnv.POSTMARK_SIGN_IN_TEMPLATE, + POSTMARK_ACTIVATION_TEMPLATE: + process.env.POSTMARK_ACTIVATION_TEMPLATE ?? + fallbackEnv.POSTMARK_ACTIVATION_TEMPLATE, + STRIPE_API_KEY: process.env.STRIPE_API_KEY ?? fallbackEnv.STRIPE_API_KEY, + STRIPE_WEBHOOK_SECRET: + process.env.STRIPE_WEBHOOK_SECRET ?? fallbackEnv.STRIPE_WEBHOOK_SECRET, + STRIPE_PRO_MONTHLY_PLAN_ID: + process.env.STRIPE_PRO_MONTHLY_PLAN_ID ?? + fallbackEnv.STRIPE_PRO_MONTHLY_PLAN_ID, + NEXT_PUBLIC_APP_URL: + process.env.NEXT_PUBLIC_APP_URL ?? fallbackEnv.NEXT_PUBLIC_APP_URL, +} + export const env = createEnv({ server: { // This is optional because it's only used in development. @@ -22,20 +70,14 @@ export const env = createEnv({ client: { NEXT_PUBLIC_APP_URL: z.string().min(1), }, - runtimeEnv: { - NEXTAUTH_URL: process.env.NEXTAUTH_URL, - NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET, - GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID, - GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET, - GITHUB_ACCESS_TOKEN: process.env.GITHUB_ACCESS_TOKEN, - DATABASE_URL: process.env.DATABASE_URL, - SMTP_FROM: process.env.SMTP_FROM, - POSTMARK_API_TOKEN: process.env.POSTMARK_API_TOKEN, - POSTMARK_SIGN_IN_TEMPLATE: process.env.POSTMARK_SIGN_IN_TEMPLATE, - POSTMARK_ACTIVATION_TEMPLATE: process.env.POSTMARK_ACTIVATION_TEMPLATE, - STRIPE_API_KEY: process.env.STRIPE_API_KEY, - STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET, - STRIPE_PRO_MONTHLY_PLAN_ID: process.env.STRIPE_PRO_MONTHLY_PLAN_ID, - NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL, - }, + runtimeEnv, + emptyStringAsUndefined: true, }) + +/** + * Utility to check whether an environment variable has been provided + * or if the application is still relying on the default placeholder. + * + * @param {keyof typeof fallbackEnv} key + */ +export const isEnvVarSet = (key) => runtimeEnv[key] !== fallbackEnv[key] diff --git a/package.json b/package.json index 00460d2..243044d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ }, "scripts": { "dev": "concurrently \"contentlayer dev\" \"next dev\"", - "build": "contentlayer build && next build", + "build": "next build", "turbo": "next dev --turbo", "start": "next start", "lint": "next lint",