.env files
Environment variables loaded from .env, .env.local and their per-mode variants in the project root when the server starts.
.env.local
DATABASE_URL=postgres://localhost:5432/acme
GIO_SESSION_SECRET=replace-me-with-32-random-bytes
# Only GIO_PUBLIC_* variables reach browser code.
GIO_PUBLIC_SITE_NAME=AcmeReference
Files and precedence
The files sit in the project root, next to app/. They are read in this order, and the first one that sets a variable wins:
| Order | File | Typical use |
|---|---|---|
| 1 | .env.development.local / .env.production.local | Machine-specific overrides for one mode. Never committed. |
| 2 | .env.local | Local secrets for every mode. Never committed. |
| 3 | .env.development / .env.production | Shared defaults for one mode. |
| 4 | .env | Shared defaults for every mode. |
- Real environment variables always win. A variable already set in the environment that starts the server is never overridden by a file.
- The mode is
developmentwhenNODE_ENV=development(asgio devsets it) andproductionotherwise,NODE_ENV=testor unset included. There is no.env.test. - When. Once, at server startup, before
gio.tomlis read, so the files can setGIO_PORTand the other variables that override it. The Node worker inherits the result. Editing a file needs a restart, in development too: the watcher ignores dotfiles.
Syntax
.env
# A comment
PLAIN=value
QUOTED="two words"
export WITH_EXPORT=allowed # the export prefix is ignored
INLINE=value # a comment after a space
MULTILINE="line 1
line 2"
DERIVED=${PLAIN}-suffix # value-suffix
LITERAL='${PLAIN} is not expanded' # single quotes keep it as written${VAR} expands a variable from the environment, from an earlier line, or from a file with higher precedence; an unknown one expands to nothing. The parser is dotenvy's, and the Node tools use a port of it, so a file means the same thing everywhere.
Errors and warnings
- A file that cannot be parsed stops startup, naming the file and line but never the value:
cannot load .env.local: invalid syntax on line 2. NODE_ENVin a file is ignored, with a warning: the mode was already decided from the real environment. Set it where the server is started.- A candidate that is not a regular file (
python -m venv .envmakes a directory) is skipped. - The startup log lists the files it read, never their values:
loaded .env files mode="production" files=.env.local, .env.production, .env.
Turning it off
| Setting | Effect |
|---|---|
[env] files = false in gio.toml | No file is loaded. |
GIO_ENV_FILES=0 (or false) | No file is loaded, whatever gio.toml says. |
GIO_ENV_FILES=1 (or true) | Files are loaded, whatever gio.toml says. |
Any other GIO_ENV_FILES value stops startup. Platforms that inject their own environment (containers, PaaS) often turn the files off so a stray .env in the image cannot apply.
Examples
Read a variable on the server
app/status/page.tsx
import React from 'react';
import type { GetServerSideProps, InferPageProps } from '@gio.js/core';
export const getServerSideProps: GetServerSideProps<{ region: string }> = async () => {
// Server-only: DEPLOY_REGION is never sent to the browser unless returned as a prop.
return { props: { region: process.env.DEPLOY_REGION ?? 'local' } };
};
export default function Status({ region }: InferPageProps<typeof getServerSideProps>) {
return <p>Served from {region}</p>;
}A public variable in browser code
components/Footer.tsx
import React from 'react';
export function Footer() {
// Inlined into the client bundle when it is built.
return <footer>{process.env.GIO_PUBLIC_SITE_NAME}</footer>;
}Good to know
- Only
GIO_PUBLIC_*reaches the browser. Those variables are inlined into the client bundles when they are built (at worker start,gio exportorgio build standalone, which freeze the values). Every otherprocess.env.Xisundefinedin the browser. The prefix is fixed, so a secret cannot leak by a renamed setting. Never put a secret in aGIO_PUBLIC_variable. - Commit
.envand.env.{mode}only if they hold no secrets, and keep the.localfiles out of git. Thecreate-giojsstarter ignores.env*.localand ships a.env.exampleto copy. gio export,gio build standalone,gio routes,gio typegenand the testing kit load the same files with the same rules and switches.giojs-server --check-configloads them too, and reports which ones it read.- Unlike Next.js,
.env.localalso applies whenNODE_ENV=test. SetGIO_ENV_FILES=0in tests that must not see local values.
Related
- Environment Variables - the guide.
- Environment variables reference - every variable GioJS reads.
[env], Configuration: .env files
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced: .env files with Next.js precedence for the server, gio export, standalone builds and the CLI; GIO_PUBLIC_* inlining; [env] files and GIO_ENV_FILES. |