Setting environment variables in Remix

Learn how to set environment variables in Remix and how to ensure that they are available in the client-side code.

·3 min read
Cover Image for Setting environment variables in Remix

When trying out Remix for the first time, you might have noticed that the process.env object is empty. This is because Remix, unlike Next.js, doesn't support loading environment variables in your client-side bundles, and that's by design.

In this tutorial, we'll learn how to set environment variables in Remix, similar to how Next.js works.

Does Remix support environment variables?

Yes and no.

During development, Remix will load environment variables from a .env file at the root of your project, but it will be ignored when you build your app for production. Again, it's not a bug or a missing feature, it's a design decision.

The Remix team suggests not committing this file to your repository, and instead using a .env.example file to show other developers what environment variables are required.

To inject environment variables into your app in production, the recommendation is to solely use the provider of your choice, rather than file-based configuration. For example, if you're using Vercel, you can use their Environment Variables feature.

Exposing environment variables to the client in Remix

When you run remix dev, Remix will load the environment variables from .env and make them available in process.env in your code.

Unlike Next.js, Remix doesn't expose these variables to the client-side bundle in any situation. So, if you want to use environment variables in your client-side code, w'll need to manually expose them to the client by adding them as a global variable using the root layout.

Collecting the environment variables that need to be exposed

Of course, you should never expose all of your environment variables to the client. Instead, you should only expose the ones that you need to use in your client-side code. For example, if you're using a third-party API that requires a public API key, you should expose that key to the client.

For example, we can create a getBrowserEnvironment function that returns an object with the environment variables that we want to expose to the client.

routes/root.tsx
function getBrowserEnvironment() {
  const env = process.env;
 
  return {
    SITE_URL: env.SITE_URL,
    DEFAULT_LOCALE: env.DEFAULT_LOCALE,
    NODE_ENV: env.NODE_ENV,
    SENTRY_DSN: env.SENTRY_DSN,
    SUPABASE_URL: env.SUPABASE_URL,
    SUPABASE_ANON_KEY: env.SUPABASE_ANON_KEY,
  };
}

In the same file, we can add a script tag to the head of the document that will expose the environment variables to the client.

routes/root.tsx
<script
  dangerouslySetInnerHTML={{
    __html: `window.ENV = ${JSON.stringify(data.ENV)}`,
  }}
/>

Thus, we can access the environment variables in the client-side code using window.ENV.

Now, we can create an isomorphic function (i.e. that works on both the client and server) we name getEnv that will return the environment variables.

get-env.ts
function isBrowser() {
  return typeof window !== 'undefined';
}
 
function getEnv() {
  return isBrowser() ? window.ENV : process.env;
}
 
export default getEnv;

When you need to access the environment variables in your client-side code, you can import the getEnv function and use it to access the environment variables.

components/seo.tsx
import getEnv from '../get-env';
 
const env = getEnv();
 
function Seo() {
  return (
    <>
      <meta name="og:url" content={env.SITE_URL} />
    </>
  );
}

Conclusion

In this tutorial, we learned how to set environment variables in Remix, and how to ensure that they're available in the client-side code. We also learned how to create an isomorphic function that will return the environment variables, regardless of whether it's being called on the client or server. This can be useful if you want to use a unified API for accessing environment variables in your code.

If you have any questions or feedback, please reach out! I'm always happy to help.


Subscribe to our Newsletter
Get the latest updates about React, Remix, Next.js, Firebase, Supabase and Tailwind CSS

Read more about Tutorials

Cover Image for Next.js 13: complete guide to Server Components and the App Directory

Next.js 13: complete guide to Server Components and the App Directory

·14 min read
Unlock the full potential of Next.js 13 with our most complete and definitive tutorial on using server components and the app directory.
Cover Image for Pagination with React.js and Supabase

Pagination with React.js and Supabase

·6 min read
Discover the best practices for paginating data using Supabase and React.js using the Supabase Postgres client
Cover Image for How to sell code with Lemon Squeezy and Github

How to sell code with Lemon Squeezy and Github

·7 min read
Sell and monetize your code by giving private access to your Github repositories using Lemon Squeezy
Cover Image for Writing clean React

Writing clean React

·9 min read
Level up your React coding skills with Typescript using our comprehensive guide on writing clean code. Start writing clean React code, today.
Cover Image for How to use MeiliSearch with React

How to use MeiliSearch with React

·12 min read
Learn how to use MeiliSearch in your React application with this guide. We will use Meiliseach to add a search engine for our blog posts
Cover Image for Programmatic Authentication with Supabase and Cypress

Programmatic Authentication with Supabase and Cypress

·3 min read
Testing code that requires users to be signed in can be tricky. In this post, we show you how to sign in programmatically with Supabase Authentication to improve the speed of your Cypress tests and increase their reliability.