Next.js Discord

Discord Forum

How to use ENVIRONMENT variables with App Router?

Unanswered
Golden northern bumble bee posted this in #help-forum
Open in Discord
Golden northern bumble beeOP
Could you folks please tell what I replace publicRuntimeConfig with when using AppRouter? It's not covered normally in the docs here https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables

56 Replies

Golden northern bumble beeOP
So currently I do like:
const { MODULE_ID, MODULE_MODE } = publicRuntimeConfig


Now with AppRouter what do I do?
@Golden northern bumble bee Could you folks please tell what I replace `publicRuntimeConfig` with when using AppRouter? It's not covered normally in the docs here https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables
inside the app router, you add a .env file and inside that file you can add your variables like this:
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword

Make sure, that you add a .local at the end, to not share them with github.

You file can look like this for private env variables:
-# .env.local
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword


You can then use them inside your code like this:
const dbHost = process.env.DB_HOST;

Keep in mind, that you can only access them in clientside component, when you give them the NEXT_PUBLIC prefix:
NEXT_PUBLIC_HELLO='I am publically accessable'
Golden northern bumble beeOP
const dbHost = process.env.DB_HOST; - but such variables are not available in the client-side components, are they?
While publicRuntimeConfig was
@Golden northern bumble bee `const dbHost = process.env.DB_HOST;` - but such variables are not available in the client-side components, are they?
Keep in mind, that you can only access them in clientside component, when you give them the NEXT_PUBLIC prefix:
NEXT_PUBLIC_HELLO='I am publically accessable'
Golden northern bumble beeOP
We don't use NEXTPUBLIC variabels as we don't need to build any of them into client side code
So I speak precisely about unprefixed variables that were avaialble via publicRutimeConfig
All env variables, that don't have the prefix NEXT_PUBLIC will only be accessable serverside
Golden northern bumble beeOP
That's the essence of my question 🙂
What did they replace publicRutimeConfig with?
remove it
Golden northern bumble beeOP
and replace with what?
no replacement. Just remove
Golden northern bumble beeOP
Then how I can get my variablers at the client-side? 🙂
@Golden northern bumble bee Then how I can get my variablers at the client-side? 🙂
I am quite confused. I thought you don't want to use them clientside?
We don't use NEXTPUBLIC variabels as we don't need to build any of them into client side code
Golden northern bumble beeOP
NEXTPUBLIC vars get built into client-side code. So your image becomes bound to your build variables. You cannot deploy it anywhere else.
To address this problem, there was publicRutimeConfig
with that, you could run your nextjs app in different environments
For example we can run:
$ MODULE_MODE=standalone npx next start
It is recommended to use environment variables instead, which also support reading runtime values. You might want to use the methods from the app router and incrementally adoping the app router. Thats what I just showed you
Golden northern bumble beeOP
How I can pass an evnironment variable to the client then?
So having your page dynamically rendered like this:
import { unstable_noStore as noStore } from 'next/cache'
 
export default function Component() {
  noStore()
  // cookies(), headers(), and other dynamic functions
  // will also opt into dynamic rendering, meaning
  // this env variable is evaluated at runtime
  const value = process.env.MY_VALUE
  // ...
}

This env variables will be evaluated at runtime
Golden northern bumble beeOP
I don't see "use client" at the top.
Which means it won't work on client
will it?
@B33fb0n3 https://tryitands.ee/
Golden northern bumble beeOP
The message is clear
So a code like this won't work:
export default function Component() {
  return (
    <button onClick={() => fetch(process.env.API_URL)... }>
      Click me
    </button>
  )
}
because API_URL will be empty
But sure, I can try...
@Golden northern bumble bee ts export default function Component() { return ( <button onClick={() => fetch(process.env.API_URL)... }> Click me </button> ) }
yea, it will be empty. However:
export default function Component() {
  return (
    <button onClick={() => fetch(process.env.NEXT_PUBLIC_API_URL)... }>
      Click me
    </button>
  )
}

Now the string is full
Golden northern bumble beeOP
Nah, it doesn't work, I just checked
So I added component like this:
'use client'
export default function Foo() {
  return <button onClick={() => console.log(process.env.NEXT_PUBLIC_FOO)}>Click me</button>
}

and then ran it as:
FOO=asd pnpm dev
And when I click the button it gives me undefined
to make sure the env variable it properly set you need to create a .env file and add the env variable there
Golden northern bumble beeOP
Sure, I have it also
.env
FOO="asd"
So FOO doesn't get magically converted to NEXT_PUBLIC_FOO
You should also name your environment variable the same as when you call it up
Golden northern bumble beeOP
I also tried this. But then it stops being a runtime variable
it's then built into client code and cannot be changed afterwards
As you might already read: you want to adopt the app router. For me that means, that there is no option for clientside runtime variables. If you need to defined them, build it beforehand
Golden northern bumble beeOP
What do you mean "adopt the app router"? 🙂
I do use App Router
So it's already adopted
The essence of my question is precisely this: What the publicRuntimeConfig functionality was replaced with? I.e.: How to configure a NextJS app with AppRouter in runtime?
As I already said mutliple times: there is no replacement. It works only for serverside variables as they get build on deployment.
Golden northern bumble beeOP
Then AppRouter turns to be a degraded direction of NextJS development really
basically because building during deployment is an anti-pattern
your docker image should not depend on WHERE it gets deployed
@B33fb0n3 thank you for trying to help man, but my question is still unanswered.
Because honestly I still believe there is a way to configure client at run-time...
@Golden northern bumble bee <@301376057326567425> thank you for trying to help man, but my question is still unanswered. Because honestly I still believe there is a way to configure client at run-time...
tell me when you found a solution, that exists before today and that I haven't mentioned yet. If you found one provide a reproduction.
@B33fb0n3 tell me when you found a solution, that exists before today and that I haven't mentioned yet. If you found one provide a reproduction.
Golden northern bumble beeOP
Ok. I expect the solution will be in reading ENV vars on server and passing them to client.

With getServerSidePropos() you could do it like:

index.tsx:
export default function Home(props: {foo: string}) {
  console.log({foo}) // will always be set
  return <div />
}

export async function getServerSideProps() {
  return {
    props: { foo: process.env.FOO as string }
  }
}
To make it clear - you didn't actually need to do this before App Router. You could just use publicRutimeConfig which has everything you need if you configure it properly via next.config.js:

next.config.js:
const nextConfig = {
  publicRuntimeConfig: {
    FOO: process.env.FOO,
    // ...