mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2026-06-05 19:15:30 -04:00
validate environment variables at build time
This commit is contained in:
@@ -8,10 +8,6 @@ export const AVATAR_PATH = "app/avatar.jpg";
|
||||
// maximum width of content wrapper (e.g. for images) in pixels
|
||||
export const MAX_WIDTH = 865;
|
||||
|
||||
// same logic as metadataBase: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#default-value
|
||||
export const BASE_URL =
|
||||
process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL}`
|
||||
: process.env.NEXT_PUBLIC_VERCEL_ENV === "preview" && process.env.NEXT_PUBLIC_VERCEL_URL
|
||||
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`
|
||||
: `http://localhost:${process.env.PORT || 3000}`;
|
||||
// defined in next.config.ts
|
||||
export const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL!;
|
||||
export const RELEASE_TIMESTAMP = process.env.NEXT_PUBLIC_RELEASE_TIMESTAMP!;
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as config from ".";
|
||||
import { BASE_URL } from "./constants";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
const metadata: Metadata = {
|
||||
const defaultMetadata: Metadata = {
|
||||
metadataBase: new URL(BASE_URL),
|
||||
title: {
|
||||
template: `%s – ${config.siteName}`,
|
||||
@@ -44,4 +44,4 @@ const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default metadata;
|
||||
export default defaultMetadata;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { vercel } from "@t3-oss/env-nextjs/presets-valibot";
|
||||
import * as v from "valibot";
|
||||
|
||||
export const env = createEnv({
|
||||
extends: [vercel()],
|
||||
server: {
|
||||
GITHUB_TOKEN: v.optional(v.pipe(v.string(), v.startsWith("ghp_"))),
|
||||
KV_REST_API_TOKEN: v.string(),
|
||||
KV_REST_API_URL: v.pipe(v.string(), v.url(), v.startsWith("https://"), v.endsWith(".upstash.io")),
|
||||
RESEND_API_KEY: v.pipe(v.string(), v.startsWith("re_")),
|
||||
RESEND_FROM_EMAIL: v.optional(v.pipe(v.string(), v.email())),
|
||||
RESEND_TO_EMAIL: v.pipe(v.string(), v.email()),
|
||||
TURNSTILE_SECRET_KEY: v.optional(v.string()),
|
||||
},
|
||||
client: {
|
||||
NEXT_PUBLIC_GISCUS_CATEGORY_ID: v.optional(v.string()),
|
||||
NEXT_PUBLIC_GISCUS_REPO_ID: v.optional(v.string()),
|
||||
NEXT_PUBLIC_ONION_DOMAIN: v.optional(v.pipe(v.string(), v.endsWith(".onion"))),
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY: v.optional(v.string()),
|
||||
NEXT_PUBLIC_UMAMI_URL: v.optional(v.pipe(v.string(), v.url())),
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID: v.optional(v.string()),
|
||||
},
|
||||
experimental__runtimeEnv: {
|
||||
NEXT_PUBLIC_GISCUS_CATEGORY_ID: process.env.NEXT_PUBLIC_GISCUS_CATEGORY_ID,
|
||||
NEXT_PUBLIC_GISCUS_REPO_ID: process.env.NEXT_PUBLIC_GISCUS_REPO_ID,
|
||||
NEXT_PUBLIC_ONION_DOMAIN: process.env.NEXT_PUBLIC_ONION_DOMAIN,
|
||||
NEXT_PUBLIC_TURNSTILE_SITE_KEY: process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY,
|
||||
NEXT_PUBLIC_UMAMI_URL: process.env.NEXT_PUBLIC_UMAMI_URL,
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID: process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID,
|
||||
},
|
||||
emptyStringAsUndefined: true,
|
||||
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Feed } from "feed";
|
||||
import { getFrontMatter, getContent } from "./posts";
|
||||
import * as config from "../config";
|
||||
import { BASE_URL } from "../config/constants";
|
||||
import { BASE_URL, RELEASE_TIMESTAMP } from "../config/constants";
|
||||
import type { Item as FeedItem } from "feed";
|
||||
|
||||
import ogImage from "../../app/opengraph-image.jpg";
|
||||
@@ -12,12 +12,12 @@ import ogImage from "../../app/opengraph-image.jpg";
|
||||
*/
|
||||
export const buildFeed = async (): Promise<Feed> => {
|
||||
const feed = new Feed({
|
||||
id: BASE_URL,
|
||||
link: BASE_URL,
|
||||
id: `${BASE_URL}`,
|
||||
link: `${BASE_URL}`,
|
||||
title: config.siteName,
|
||||
description: config.longDescription,
|
||||
copyright: config.licenseUrl,
|
||||
updated: new Date(process.env.RELEASE_DATE || Date.now()),
|
||||
updated: new Date(RELEASE_TIMESTAMP),
|
||||
image: `${BASE_URL}${ogImage.src}`,
|
||||
feedLinks: {
|
||||
rss: `${BASE_URL}/feed.xml`,
|
||||
@@ -41,7 +41,7 @@ export const buildFeed = async (): Promise<Feed> => {
|
||||
author: [
|
||||
{
|
||||
name: config.authorName,
|
||||
link: BASE_URL,
|
||||
link: `${BASE_URL}`,
|
||||
},
|
||||
],
|
||||
date: new Date(post.date),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import defaultMetadata from "../config/metadata";
|
||||
import defaultMetadata from "../config/seo";
|
||||
import type { Metadata } from "next";
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user