Env Diff
Two environments side by side, values masked by default. A variable missing from one side is drawn differently from one whose value merely differs — "not set" and "set to something else" have different causes.
src/components/ui/env-diff.tsxAbout
From the component's own source, where it was written.
Two environments' variables side by side.
Values are masked by default and revealed per row. This is the screen someone opens when staging behaves differently from production, and it is exactly the screen that gets screenshotted into a shared channel with a database password in it.
A variable missing from one side is the finding, and it is drawn differently from one whose value merely differs — "not set" and "set to something else" have completely different causes. Both are ranked above equal rows.
Whitespace and length differences are called out even when the masked values look identical, because a trailing newline in a secret is a genuinely common and genuinely invisible outage.
One grid owns the columns and every row inherits them through subgrid. Per-row grids only agree on fixed tracks: 1fr and auto resolve against whatever that row holds, so a row with a reveal button lines up differently from one without.
Install
npx astralyx-ui add env-diff
Usage
import { EnvDiff } from '@/components/ui/env-diff'
<EnvDiff left={staging} right={production} leftLabel="Staging" rightLabel="Production" />Composer
Change the props and the source below follows.
FEATURE_NEW_CHECKOUTtruenot setSENTRY_DSNnot sethttps://abc@sentry.io/42DATABASE_URL••••••••••••••••••••••••••••••••LOG_LEVELdebuginfoREDIS_URLredis://cache.staging:6379redis://cache.prod:6379SESSION_SECRET••••••••••••••••••••••••••••••••
<EnvDiff left={staging} right={production} />Examples
Staging against production
<EnvDiff left={staging} right={production} />API
Generated from the source, so it cannot fall behind the code. One table per exported component, then hooks, functions and types.
EnvDiff
Extends Omit<ComponentProps<'div'>, 'children'>.
| Prop | Type | Default | Description |
|---|---|---|---|
| left | EnvEntry[] | required | { key, value, secret? }. A value of undefined means not set. |
| right | EnvEntry[] | required | { key, value, secret? }. A value of undefined means not set. |
| leftLabel | ReactNode | 'Left' | — |
| rightLabel | ReactNode | 'Right' | — |
| notSetLabel | ReactNode | 'not set' | — |
| whitespaceNote | ReactNode | 'differs only in whitespace' | — |
| revealLabel | string | 'Reveal value' | — |
| hideLabel | string | 'Hide value' | — |
| sameLabel | ReactNode | 'identical' | — |
| showSame | boolean | false | — |
| toggleSameLabel | (count: number) => ReactNode | DEFAULT_TOGGLE_SAME_LABEL | — |
| hideSameLabel | ReactNode | 'Hide identical' | — |
Types
EnvEntry
Two environments' variables side by side.
| Field | Type | Description |
|---|---|---|
| key | string | — |
| value | string | — |
| secret? | boolean | — |
Behaviour
| Topic | Detail | Description |
|---|---|---|
| masking | per row | This is the screen someone opens when staging differs from production, and the screen that gets screenshotted into a shared channel with a password in it. |
| whitespace | called out | Values differing only in whitespace are flagged — a trailing newline in a secret is invisible and takes a service down. |
| ordering | differences first | Missing and differing rows above identical ones, which are collapsed behind a count. |