t3-env
t3-env copied to clipboard
Ability to load environment variables at runtime, not build time
I wonder if it is possible to load the environment variables at runtime, as with "https://github.com/expatfile/next-runtime-env". This is not possible in the example with nextjs.
Yeah, I assumed t3-env already did this! 🥲
It's important for self-hostable applications that are packaged into a docker image, end users should be able to edit the runtime env
Would you accept PR for this? I could try to implement a solution
I think we can make t3-env compatible with next-runtime-env at least! I'll take a look.
@baptisteArno I would be very happy if, if you find a solution, you share it here. I have been looking for something like this for some time. Thank you very much!
This works:
// src/env.mjs
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
const readVariable = (key) => {
if(typeof window === 'undefined') return process.env[key]
return window.__ENV[key]
}
export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
OPEN_AI_API_KEY: z.string().min(1),
},
client: {
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
},
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
OPEN_AI_API_KEY: process.env.OPEN_AI_API_KEY,
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
readVariable(NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY),
},
});
Would you accept PR for this? I could try to implement a solution
Yes
Would love to hear of any updates on this issue🤔
In the project I'm working we adopted the t3-env lib with nextjs, to work around this validation problem in the build time I added an env var to skip the validation. Package.json
{
"scripts": {
"dev": "yarn generate && NODE_OPTIONS='--inspect' next dev",
"build": "yarn generate && SKIP_ENV_VALIDATIONS='true' next build",
"start": "next start",
}
}
env.mjs:
export const env = createEnv({
isServer: typeof window === 'undefined' || process.env.NODE_ENV === 'test',
/*
* Serverside Environment variables, not available on the client.
* Will throw if you access these variables on the client.
*/
server: {
},
/*
* Environment variables available on the client and server.
*
*/
shared: {
NODE_ENV: z.enum(['test', 'development', 'production'])
.optional()
.default('production'),
STAGE: z.enum(['local', 'dev', 'stg', 'prod']).default('prod'),
APP_LOG_LEVEL: z
.string()
.optional()
.default('info')
.transform((data) => data.toLowerCase()),
},
/*
* Environment variables available on the client.
*
* 💡 You'll get type errors if these are not prefixed with NEXT_PUBLIC_.
*/
client: {
},
/*
* Due to how Next.js bundles environment variables on Edge and Client,
* we need to manually destructure them to make sure all are included in bundle.
*
* 💡 You'll get type errors if not all variables from `server` & `client` are included here.
* All the env vars must end with the suffix _ENV to avoid a cycle import on the env-nextjs that enters in loop
*/
runtimeEnv: {
NODE_ENV: process.env.NODE_ENV,
STAGE: process.env.STAGE,
APP_LOG_LEVEL: process.env.APP_LOG_LEVEL,
},
skipValidation: process.env.SKIP_ENV_VALIDATIONS === 'true'
});
In this way I'm able to skip the validation for the build
This works:
// src/env.mjs import { createEnv } from "@t3-oss/env-nextjs"; import { z } from "zod"; const readVariable = (key) => { if(typeof window === 'undefined') return process.env[key] return window.__ENV[key] } export const env = createEnv({ server: { DATABASE_URL: z.string().url(), OPEN_AI_API_KEY: z.string().min(1), }, client: { NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1), }, runtimeEnv: { DATABASE_URL: process.env.DATABASE_URL, OPEN_AI_API_KEY: process.env.OPEN_AI_API_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: readVariable(NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY), }, });
I would like something like this, but for async functions. #146
The correct way is what @rochaalexandre posted but SKIP_ENV_VALIDATION
instead of SKIP_ENV_VALIDATIONS