# Remix

## Prerequisites

Start with a [Remix v2 app using Vite](https://v2.remix.run/docs/start/quickstart/) and the Node.js runtime. This guide uses @remix-run/serve for production.

## Install

In your Remix project, install Dotenvx.

**npm**

```console
$ npm install @dotenvx/dotenvx
```

**pnpm**

```console
$ pnpm add @dotenvx/dotenvx
```

## Encrypt

Start with a secret value in the .env file at your project root, like:

```dotenv
# .env
HELLO="Secret"
```

Encrypt it with a single command.

**npm**

```console
$ npx dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
```

**pnpm**

```console
$ pnpm exec dotenvx encrypt
◈ encrypted .env (022 0D8) via .env.keys ⛉
```

The values become ciphertext and only your private key can unlock them.

```dotenv
# .env
DOTENV_PUBLIC_KEY="0220d830351410598be484f43a7b07097e09851f50426832876e8b5815a1752990"

HELLO="encrypted:BHLTACNJMr00nTG6yXpkCyWFKF/MY0ajN855tg3uVtKopTe2AGzSkQlcPd21pTOT3Ci8IKrdIg2TMZFoq1mDR6yb06QCRvqHXtpkZkAHYCEHfeWqqC8tMFovcYq5JS2uZSrC/qUGDA=="
```

## Commit

Commit your encrypted .env files with your code. It's safe. Now you can securely share secrets through git.

```console
$ git add .env
$ git commit -m "encrypt .env"
```

## Ship

Read your value in a server loader:

```tsx
// app/routes/_index.tsx
import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';

export async function loader() {
  return json({ hello: process.env.HELLO });
}

export default function Index() {
  const { hello } = useLoaderData<typeof loader>();
  return <h1>Hello {hello}</h1>;
}
```

HELLO is a demonstration value. Loader responses reach the browser; use real secrets inside loaders or actions without returning them.

Update these scripts in package.json, keeping your other scripts:

**package.json**

```json
{
  "scripts": {
    "dev": "dotenvx run -- remix vite:dev",
    "build": "remix vite:build",
    "start": "dotenvx run -f .env.production --strict -- remix-serve ./build/server/index.js"
  }
}
```

Run your app:

**npm**

```console
$ npm run dev
⟐ injected env (2) from .env (022 0D8) via .env.keys
```

**pnpm**

```console
$ pnpm dev
⟐ injected env (2) from .env (022 0D8) via .env.keys
```

Dotenvx loads and decrypts .env before Remix starts. Your loader reads process.env on the server at request time.

Visit [http://localhost:5173](http://localhost:5173) to see Hello Secret.

Browser response at [http://localhost:5173](http://localhost:5173):

```text
Hello Secret
```

[**Public browser variables** Alternative →](https://dotenvx.com/docs/remix/public-variables.md)

## Share

Have teammates? Share access with Dotenvx Armor ⛨

Log in to Dotenvx.

**npm**

```console
$ npx dotenvx login
◉ logged in (username)
```

**pnpm**

```console
$ pnpm exec dotenvx login
◉ logged in (username)
```

Create the Armored Key ⛨

**npm**

```console
$ npx dotenvx armor up
⛨ armored .env (022 0D8)
```

**pnpm**

```console
$ pnpm exec dotenvx armor up
⛨ armored .env (022 0D8)
```

Invite your teammate.

**npm**

```console
$ npx dotenvx armor invite
⛨ invited person@example.com to team
```

**pnpm**

```console
$ pnpm exec dotenvx armor invite
⛨ invited person@example.com to team
```

Your teammate accepts the invitation, pulls the repository, installs dependencies, and logs in with dotenvx login. They can then run the app:

**npm**

```console
$ npm run dev
⟐ injected env (2) from .env (022 0D8) via Armor ⛨
```

**pnpm**

```console
$ pnpm dev
⟐ injected env (2) from .env (022 0D8) via Armor ⛨
```

Visit [http://localhost:5173](http://localhost:5173) to see Hello Secret.

Browser response at [http://localhost:5173](http://localhost:5173):

```text
Hello Secret
```

[**Share a private key** Alternative →](https://dotenvx.com/docs/remix/share-private-key.md)

## Production

Create a .env.production file.

```dotenv
# .env.production
HELLO="Production"
```

Encrypt it with an Enclaved Key ◊

**npm**

```console
$ npx dotenvx encrypt -f .env.production
◈ encrypted .env.production (022 0D8) via Armor Enclave ◊
```

**pnpm**

```console
$ pnpm exec dotenvx encrypt -f .env.production
◈ encrypted .env.production (022 0D8) via Armor Enclave ◊
```

When prompted, choose **Enclaved**, select your deployment service, connection, and resource, and use DOTENV_PRIVATE_KEY_PRODUCTION as the private key name.

Commit .env.production.

```console
$ git add -f .env.production
$ git commit -m "encrypt .env.production"
```

Install dependencies and build your app in your deployment build step:

**npm**

```console
$ npm install
$ npm run build
```

**pnpm**

```console
$ pnpm install
$ pnpm build
```

This server-rendered example only needs its secret at runtime, so the build script does not decrypt it.

Deploy the compiled build directory, package.json, runtime dependencies, and encrypted .env.production file to the selected resource. Keep .env.production at the project root and .env.keys on your local machine.

Set HOST to 0.0.0.0 and PORT to the port your host expects. From the project root, run:

**npm**

```console
$ npm start
```

**pnpm**

```console
$ pnpm start
```

Dotenvx loads and decrypts .env.production with your Enclaved Key ◊

Open your deployed app's URL to see Hello Production.

Browser response at [https://your-app.example.com](https://your-app.example.com):

```text
Hello Production
```

[**Other server setups** Alternative →](https://dotenvx.com/docs/remix/server-setups.md)

[**Deploy with a private key** Alternative →](https://dotenvx.com/docs/remix/deploy-private-key.md)

## Conclusion

You've encrypted your secrets, shared access with Armor, and loaded production secrets in Remix with an Enclaved Key. Your secrets now travel with your code.
