or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core.mdindex.mdpresets-arktype.mdpresets-valibot.mdpresets-zod.md

core.mddocs/

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

```