0
# Environment Schema Creation
1
2
Core functionality for creating typesafe environment variable schemas with Next.js-specific validation rules and runtime compatibility enforcement.
3
4
## Capabilities
5
6
### createEnv Function
7
8
Creates a new environment variable schema with Next.js-specific configurations, enforcing the NEXT_PUBLIC_ prefix for client-side variables and providing runtime validation.
9
10
```typescript { .api }
11
/**
12
* Create a new environment variable schema with Next.js-specific configurations
13
* @param opts - Configuration options for the environment schema
14
* @returns Validated environment variables with full type safety
15
*/
16
function createEnv<
17
TServer extends StandardSchemaDictionary = NonNullable<unknown>,
18
TClient extends Record<`NEXT_PUBLIC_${string}`, StandardSchemaV1> = NonNullable<unknown>,
19
TShared extends StandardSchemaDictionary = NonNullable<unknown>,
20
const TExtends extends Array<Record<string, unknown>> = [],
21
TFinalSchema extends StandardSchemaV1<{}, {}> = DefaultCombinedSchema<TServer, TClient, TShared>
22
>(opts: Options<TServer, TClient, TShared, TExtends, TFinalSchema>): CreateEnv<TFinalSchema, TExtends>;
23
```
24
25
**Generic Parameters:**
26
- `TServer` - Schema dictionary for server-side environment variables
27
- `TClient` - Schema dictionary for client-side environment variables (must use NEXT_PUBLIC_ prefix)
28
- `TShared` - Schema dictionary for shared environment variables (available on both server and client)
29
- `TExtends` - Array of preset environment objects to extend from
30
- `TFinalSchema` - Final combined schema type
31
32
### Configuration Options
33
34
Configuration options for the createEnv function with Next.js-specific runtime environment handling.
35
36
```typescript { .api }
37
type Options<
38
TServer extends StandardSchemaDictionary,
39
TClient extends Record<`NEXT_PUBLIC_${string}`, StandardSchemaV1>,
40
TShared extends StandardSchemaDictionary,
41
TExtends extends Array<Record<string, unknown>>,
42
TFinalSchema extends StandardSchemaV1<{}, {}>
43
> = Omit<
44
StrictOptions<"NEXT_PUBLIC_", TServer, TClient, TShared, TExtends> &
45
ServerClientOptions<"NEXT_PUBLIC_", TServer, TClient> &
46
CreateSchemaOptions<TServer, TClient, TShared, TFinalSchema>,
47
"runtimeEnvStrict" | "runtimeEnv" | "clientPrefix"
48
> & (
49
| {
50
/** Manual destruction of process.env. Required for Next.js < 13.4.4 */
51
runtimeEnv: StrictOptions<"NEXT_PUBLIC_", TServer, TClient, TShared, TExtends>["runtimeEnvStrict"];
52
experimental__runtimeEnv?: never;
53
}
54
| {
55
runtimeEnv?: never;
56
/**
57
* Can be used for Next.js ^13.4.4 since they stopped static analysis of server side process.env.
58
* Only client side process.env is statically analyzed and needs to be manually destructured.
59
*/
60
experimental__runtimeEnv: Record<
61
| {
62
[TKey in keyof TClient]: TKey extends `NEXT_PUBLIC_${string}` ? TKey : never;
63
}[keyof TClient]
64
| {
65
[TKey in keyof TShared]: TKey extends string ? TKey : never;
66
}[keyof TShared],
67
string | boolean | number | undefined
68
>;
69
}
70
);
71
```
72
73
**Configuration Properties:**
74
75
**Schema Definition:**
76
- `server?: TServer` - Server-side environment variable schemas (not available on client)
77
- `client?: TClient` - Client-side environment variable schemas (must be prefixed with NEXT_PUBLIC_)
78
- `shared?: TShared` - Shared environment variable schemas (available on both server and client)
79
- `extends?: TExtends` - Array of preset environment objects to extend from
80
81
**Runtime Environment:**
82
- `runtimeEnv?: Record<string, any>` - Manual process.env destruction for Next.js < 13.4.4
83
- `experimental__runtimeEnv?: Record<string, any>` - Experimental runtime environment for Next.js >= 13.4.4
84
85
**Base Configuration Options:**
86
- `isServer?: boolean` - How to determine whether the app is running on the server or the client (default: `typeof window === "undefined"`)
87
- `onValidationError?: (issues: readonly StandardSchemaV1.Issue[]) => never` - Called when validation fails (default: logs error and throws)
88
- `onInvalidAccess?: (variable: string) => never` - Called when server-side environment variable is accessed on client (default: throws error)
89
- `skipValidation?: boolean` - Whether to skip validation of environment variables (default: `false`)
90
- `emptyStringAsUndefined?: boolean` - Treat empty strings as undefined for better default value handling (default: `false`)
91
- `createFinalSchema?: (shape: TServer & TClient & TShared, isServer: boolean) => TFinalSchema` - Custom function to combine the schemas
92
93
## Usage Examples
94
95
### Basic Environment Schema
96
97
```typescript
98
import { createEnv } from "@t3-oss/env-nextjs";
99
import { z } from "zod";
100
101
const env = createEnv({
102
server: {
103
DATABASE_URL: z.string().url(),
104
JWT_SECRET: z.string().min(32),
105
},
106
client: {
107
NEXT_PUBLIC_APP_URL: z.string().url(),
108
NEXT_PUBLIC_ANALYTICS_ID: z.string().min(1),
109
},
110
runtimeEnv: {
111
DATABASE_URL: process.env.DATABASE_URL,
112
JWT_SECRET: process.env.JWT_SECRET,
113
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
114
NEXT_PUBLIC_ANALYTICS_ID: process.env.NEXT_PUBLIC_ANALYTICS_ID,
115
},
116
});
117
```
118
119
### With Shared Variables
120
121
```typescript
122
import { createEnv } from "@t3-oss/env-nextjs";
123
import { z } from "zod";
124
125
const env = createEnv({
126
server: {
127
DATABASE_URL: z.string().url(),
128
},
129
client: {
130
NEXT_PUBLIC_APP_URL: z.string().url(),
131
},
132
shared: {
133
NODE_ENV: z.enum(["development", "test", "production"]),
134
APP_VERSION: z.string().default("1.0.0"),
135
},
136
runtimeEnv: {
137
DATABASE_URL: process.env.DATABASE_URL,
138
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
139
NODE_ENV: process.env.NODE_ENV,
140
APP_VERSION: process.env.APP_VERSION,
141
},
142
});
143
```
144
145
### Experimental Runtime Environment (Next.js >= 13.4.4)
146
147
```typescript
148
import { createEnv } from "@t3-oss/env-nextjs";
149
import { z } from "zod";
150
151
const env = createEnv({
152
server: {
153
DATABASE_URL: z.string().url(),
154
JWT_SECRET: z.string().min(32),
155
},
156
client: {
157
NEXT_PUBLIC_APP_URL: z.string().url(),
158
},
159
shared: {
160
NODE_ENV: z.enum(["development", "test", "production"]),
161
},
162
// Only specify client and shared variables
163
experimental__runtimeEnv: {
164
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
165
NODE_ENV: process.env.NODE_ENV,
166
},
167
});
168
```
169
170
### Extending Presets
171
172
```typescript
173
import { createEnv } from "@t3-oss/env-nextjs";
174
import { vercel } from "@t3-oss/env-nextjs/presets-zod";
175
import { z } from "zod";
176
177
const preset = vercel();
178
179
const env = createEnv({
180
server: {
181
DATABASE_URL: z.string().url(),
182
},
183
client: {
184
NEXT_PUBLIC_APP_URL: z.string().url(),
185
},
186
extends: [preset],
187
runtimeEnv: {
188
DATABASE_URL: process.env.DATABASE_URL,
189
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
190
// Preset variables are automatically available
191
},
192
});
193
```
194
195
### With Transformations
196
197
```typescript
198
import { createEnv } from "@t3-oss/env-nextjs";
199
import { z } from "zod";
200
201
const env = createEnv({
202
server: {
203
PORT: z.string().transform(Number),
204
ENABLE_LOGGING: z.string().transform((val) => val === "true"),
205
},
206
client: {
207
NEXT_PUBLIC_API_URL: z.string().url(),
208
},
209
runtimeEnv: {
210
PORT: process.env.PORT,
211
ENABLE_LOGGING: process.env.ENABLE_LOGGING,
212
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
213
},
214
});
215
216
// env.PORT is now a number
217
// env.ENABLE_LOGGING is now a boolean
218
```
219
220
## Error Handling
221
222
The package throws validation errors in the following scenarios:
223
224
- **Invalid Environment Variables**: When environment variables don't match their schema validation rules
225
- **Missing Required Variables**: When required environment variables are not provided in runtimeEnv
226
- **Client Access Violation**: When server-side variables are accessed on the client-side (throws runtime error)
227
- **Prefix Violation**: When client-side variables don't use the required NEXT_PUBLIC_ prefix (compile-time error)
228
- **Schema Mismatch**: When runtimeEnv keys don't match the defined schema keys
229
230
```typescript
231
// This will cause a compile-time error
232
createEnv({
233
server: {
234
// @ts-expect-error - server variables cannot have NEXT_PUBLIC_ prefix
235
NEXT_PUBLIC_SECRET: z.string(),
236
},
237
client: {
238
// @ts-expect-error - client variables must have NEXT_PUBLIC_ prefix
239
API_KEY: z.string(),
240
},
241
runtimeEnv: {},
242
});
243
```