Skip to content

Commit

Permalink
add t3-oss/env-nextjs to validate envs before build and at runtime #8
Browse files Browse the repository at this point in the history
  • Loading branch information
ukorvl committed Oct 5, 2023
1 parent 588de06 commit 921cc6a
Show file tree
Hide file tree
Showing 17 changed files with 148 additions and 48 deletions.
55 changes: 55 additions & 0 deletions app/env.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {createEnv} from '@t3-oss/env-nextjs';
import {z} from 'zod';

const notEmptyString = z.string().min(1);
const number = z.string().refine(v => !Number.isNaN(Number(v))).transform(Number);
const boolean = z.string()
.refine(v => v === 'true' || v === 'false' || v === '')
.transform((value) => value === 'true');

const server = {};

const client = {
NEXT_PUBLIC_GA_TRACKING_ID: notEmptyString,
NEXT_PUBLIC_FORMSPREE_ID: notEmptyString,
NEXT_PUBLIC_DISABLE_GA_IN_DEV_MODE: boolean,
NEXT_PUBLIC_INSTAGRAM_ADDRESS: notEmptyString.url(),
NEXT_PUBLIC_FACEBOOK_ADDRESS: notEmptyString.url(),
NEXT_PUBLIC_WHATSAPP_ADDRESS: notEmptyString.url(),
NEXT_PUBLIC_TELEGRAM_ADDRESS: notEmptyString.url(),
NEXT_PUBLIC_CONTACT_EMAIL: notEmptyString.email(),
NEXT_PUBLIC_CONTACT_PHONE: notEmptyString,
NEXT_PUBLIC_LOCATION_GOOGLE_MAPS_LINK: notEmptyString.url(),
NEXT_PUBLIC_LOCATION_ADDRESS_TEXT: notEmptyString,
NEXT_PUBLIC_GA_TRACKING_ID: notEmptyString,
NEXT_PUBLIC_HOTJAR_ID: notEmptyString,
NEXT_PUBLIC_HOTJAR_SNIPPET_VERSION: number,
NEXT_PUBLIC_FORMSPREE_ID: notEmptyString,
};

const shared = {
NODE_ENV: z.enum(['development', 'production']),
};

export const env = createEnv({
server,
client,
shared,
experimental__runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
NEXT_PUBLIC_GA_TRACKING_ID: process.env.NEXT_PUBLIC_GA_TRACKING_ID,
NEXT_PUBLIC_FORMSPREE_ID: process.env.NEXT_PUBLIC_FORMSPREE_ID,
NEXT_PUBLIC_DISABLE_GA_IN_DEV_MODE: process.env.NEXT_PUBLIC_DISABLE_GA_IN_DEV_MODE,
NEXT_PUBLIC_INSTAGRAM_ADDRESS: process.env.NEXT_PUBLIC_INSTAGRAM_ADDRESS,
NEXT_PUBLIC_FACEBOOK_ADDRESS: process.env.NEXT_PUBLIC_FACEBOOK_ADDRESS,
NEXT_PUBLIC_WHATSAPP_ADDRESS: process.env.NEXT_PUBLIC_WHATSAPP_ADDRESS,
NEXT_PUBLIC_TELEGRAM_ADDRESS: process.env.NEXT_PUBLIC_TELEGRAM_ADDRESS,
NEXT_PUBLIC_CONTACT_EMAIL: process.env.NEXT_PUBLIC_CONTACT_EMAIL,
NEXT_PUBLIC_CONTACT_PHONE: process.env.NEXT_PUBLIC_CONTACT_PHONE,
NEXT_PUBLIC_LOCATION_GOOGLE_MAPS_LINK: process.env.NEXT_PUBLIC_LOCATION_GOOGLE_MAPS_LINK,
NEXT_PUBLIC_LOCATION_ADDRESS_TEXT: process.env.NEXT_PUBLIC_LOCATION_ADDRESS_TEXT,
NEXT_PUBLIC_HOTJAR_SNIPPET_VERSION: process.env.NEXT_PUBLIC_HOTJAR_SNIPPET_VERSION,
NEXT_PUBLIC_HOTJAR_ID: process.env.NEXT_PUBLIC_HOTJAR_ID,
},
});

4 changes: 3 additions & 1 deletion app/origin.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
import {env} from './env.mjs';

export const origin =
process.env.NODE_ENV === 'production' ? 'https://salsaviva.am' : 'http://localhost:3000';
env.NODE_ENV === 'production' ? 'https://salsaviva.am' : 'http://localhost:3000';
3 changes: 2 additions & 1 deletion components/pages/Contact/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {FormikContext, useFormik} from 'formik';
import Button from '@/components/shared/Button/Button';
import AppearInViewport from '@/components/shared/AppearInViewport/AppearInViewport';
import useFormspree from '@/lib/formspree/useFormspree';
import {env} from '@/app/env.mjs';
import validationSchema, {ContactFormData} from './validationSchema';
import FormField from './FormField';

Expand All @@ -19,7 +20,7 @@ const initialValues = {
message: '',
} satisfies ContactFormData;

const {NEXT_PUBLIC_FORMSPREE_ID} = process.env;
const {NEXT_PUBLIC_FORMSPREE_ID} = env;

/**
* @param {FormProps} props Props.
Expand Down
3 changes: 2 additions & 1 deletion components/shared/Footer/Location.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import clsx from 'clsx';
import {memo} from 'react';
import {env} from '@/app/env.mjs';
import UniversalLink from '../UniversalLink/UniversalLink';

const {NEXT_PUBLIC_LOCATION_ADDRESS_TEXT, NEXT_PUBLIC_LOCATION_GOOGLE_MAPS_LINK} = process.env;
const {NEXT_PUBLIC_LOCATION_ADDRESS_TEXT, NEXT_PUBLIC_LOCATION_GOOGLE_MAPS_LINK} = env;

const containerCn = clsx('flex', 'justify-center', 'flex-nowrap', 'gap-4');
const addressCn = clsx('not-italic');
Expand Down
3 changes: 2 additions & 1 deletion components/shared/Footer/Mail.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import clsx from 'clsx';
import {memo} from 'react';
import {env} from '@/app/env.mjs';
import UniversalLink from '../UniversalLink/UniversalLink';

const {NEXT_PUBLIC_CONTACT_EMAIL} = process.env;
const {NEXT_PUBLIC_CONTACT_EMAIL} = env;

const containerCn = clsx('flex', 'justify-center');
const anchorCn = clsx('animated-link');
Expand Down
3 changes: 2 additions & 1 deletion components/shared/Footer/Phone.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import clsx from 'clsx';
import {memo} from 'react';
import {env} from '@/app/env.mjs';

const {NEXT_PUBLIC_CONTACT_PHONE} = process.env;
const {NEXT_PUBLIC_CONTACT_PHONE} = env;

const containerCn = clsx('flex', 'justify-center');
const telCn = clsx('animated-link', 'tracking-wider');
Expand Down
3 changes: 2 additions & 1 deletion components/shared/SocialIcons/iconsConfig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {faFacebook, faInstagram, faTelegram, faWhatsapp} from '@fortawesome/free-brands-svg-icons';
import {FontAwesomeIconProps} from '@fortawesome/react-fontawesome';
import {env} from '@/app/env.mjs';

/**
* Icon configuration.
Expand All @@ -13,7 +14,7 @@ const {
NEXT_PUBLIC_INSTAGRAM_ADDRESS,
NEXT_PUBLIC_TELEGRAM_ADDRESS,
NEXT_PUBLIC_WHATSAPP_ADDRESS,
} = process.env;
} = env;

/**
* Social icons config.
Expand Down
4 changes: 3 additions & 1 deletion components/shared/TopMenu/topMenuCongif.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {env} from '@/app/env.mjs';

const {
NEXT_PUBLIC_FACEBOOK_ADDRESS,
NEXT_PUBLIC_INSTAGRAM_ADDRESS,
NEXT_PUBLIC_TELEGRAM_ADDRESS,
NEXT_PUBLIC_WHATSAPP_ADDRESS,
} = process.env;
} = env;

/**
* Top menu configuration.
Expand Down
3 changes: 2 additions & 1 deletion lib/gtag/WithGtag.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {ReactElement} from 'react';
import Script from 'next/script';
import {env} from '@/app/env.mjs';
import * as gtag from './gtag';

/**
Expand All @@ -8,7 +9,7 @@ import * as gtag from './gtag';
* @returns Layout.
*/
const WithGtag = (): ReactElement => {
if (gtag.disableInDevMode && process.env.NODE_ENV !== 'production') {
if (gtag.disableInDevMode && env.NODE_ENV !== 'production') {
return <></>;
}

Expand Down
7 changes: 4 additions & 3 deletions lib/gtag/gtag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const disableInDevMode =
process.env.NEXT_PUBLIC_DISABLE_GA_IN_DEV_MODE?.toLowerCase() === 'true';
export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_TRACKING_ID;
import {env} from '@/app/env.mjs';

export const disableInDevMode = env.NEXT_PUBLIC_DISABLE_GA_IN_DEV_MODE;
export const GA_TRACKING_ID = env.NEXT_PUBLIC_GA_TRACKING_ID;

if (!disableInDevMode && !GA_TRACKING_ID) {
throw new Error('NEXT_PUBLIC_GA_TRACKING_ID environment variable should be set.');
Expand Down
3 changes: 2 additions & 1 deletion lib/hotjar/useInitHotjar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import {useEffect} from 'react';
import Hotjar from '@hotjar/browser';
import {env} from '@/app/env.mjs';

const {NODE_ENV, NEXT_PUBLIC_HOTJAR_ID, NEXT_PUBLIC_HOTJAR_SNIPPET_VERSION} = process.env;
const {NODE_ENV, NEXT_PUBLIC_HOTJAR_ID, NEXT_PUBLIC_HOTJAR_SNIPPET_VERSION} = env;

/**
* Initialize Hotjar.
Expand Down
10 changes: 0 additions & 10 deletions next.config.js

This file was deleted.

14 changes: 14 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import withBundleAnalyzer from '@next/bundle-analyzer';
// eslint-disable-next-line import/order
import './app/env.mjs';

/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
};

const withAnalyzer = withBundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});

export default withAnalyzer(nextConfig);
46 changes: 46 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@hotjar/browser": "^1.0.9",
"@t3-oss/env-nextjs": "^0.7.0",
"@tailwindcss/forms": "^0.5.6",
"@types/node": "20.1.1",
"@types/react": "18.2.6",
Expand Down
9 changes: 8 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "types/*", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"include": [
"next-env.d.ts",
"types/*",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
"app/env.mjs"
],
"exclude": ["node_modules"]
}
25 changes: 0 additions & 25 deletions types/env.d.ts

This file was deleted.

0 comments on commit 921cc6a

Please sign in to comment.