diff --git a/apps/playgrounds/vite/README.md b/apps/playgrounds/vite/README.md
index 38ec30d35..e5b0dcbff 100644
--- a/apps/playgrounds/vite/README.md
+++ b/apps/playgrounds/vite/README.md
@@ -115,6 +115,6 @@ For more information, see the [@arkenv/vite-plugin documentation](https://arkenv
2. **Automatic Filtering**: The plugin automatically filters the schema to only expose `VITE_*` prefixed variables to the client, preventing server-only variables from leaking into the bundle.
-3. **Type Safety**: With the `vite-env.d.ts` setup, `import.meta.env` is fully typesafe with autocomplete and type checking.
+3. **Typesafety**: With the `vite-env.d.ts` setup, `import.meta.env` is fully typesafe with autocomplete and type checking.
4. **Build-Time Validation**: Missing or invalid environment variables will cause the dev server to fail to start and production builds to fail with clear error messages.
diff --git a/apps/playgrounds/vite/src/vite-env.d.ts b/apps/playgrounds/vite/src/vite-env.d.ts
index 05a012746..58f46eef3 100644
--- a/apps/playgrounds/vite/src/vite-env.d.ts
+++ b/apps/playgrounds/vite/src/vite-env.d.ts
@@ -19,3 +19,7 @@ interface ViteTypeOptions {
// Now import.meta.env is totally typesafe and based on your `Env` schema definition
// Only VITE_* prefixed variables will be included (PORT is excluded)
interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
diff --git a/apps/www/bin/twoslash-mdx.ts b/apps/www/bin/twoslash-mdx.ts
index 062839aa3..bacfb4913 100644
--- a/apps/www/bin/twoslash-mdx.ts
+++ b/apps/www/bin/twoslash-mdx.ts
@@ -14,7 +14,8 @@ const content = fs.readFileSync(mdxPath, "utf8");
// which contains compilerOptions, extraFiles, etc.
const options = arktypeTwoslashOptions.twoslashOptions;
-const codeBlockRegex = /```(ts|js) twoslash(?:.*)\r?\n([\s\S]*?)\r?\n```/g;
+const codeBlockRegex =
+ /```(ts|tsx|js|jsx) twoslash(?:.*)\r?\n([\s\S]*?)\r?\n```/g;
let blockIndex = 1;
for (const match of content.matchAll(codeBlockRegex)) {
diff --git a/apps/www/content/docs/bun-plugin/index.mdx b/apps/www/content/docs/bun-plugin/index.mdx
index fbbd7c92a..f037c69cd 100644
--- a/apps/www/content/docs/bun-plugin/index.mdx
+++ b/apps/www/content/docs/bun-plugin/index.mdx
@@ -1,21 +1,25 @@
---
title: Introduction
icon: Album
+description: The ArkEnv plugin for Bun lets you validate environment variables at build-time and runtime with ArkEnv.
---
-## What is this?
+> [!IMPORTANT]
+> This plugin requires [ArkType](https://arktype.io) to be installed.
-The ArkEnv plugin for Bun lets you validate environment variables at build-time and runtime with ArkEnv.
+## Quickstart
-It supports a **simple setup** for most projects, automatically discovering your schema from `./src/env.ts` or `./env.ts`.
+### 1. Installation
-## Usage
+```package-install
+@arkenv/bun-plugin arkenv
+```
-### Simple setup (recommended)
+### 2. Configure Plugin
The simple setup automatically discovers your schema from `src/env.ts` or `env.ts`. This requires configuration in **both** `bunfig.toml` (for `Bun.serve`) and your build script (for `Bun.build`).
-#### 1. Create your schema
+#### Create your schema
```ts title="src/env.ts" twoslash
import { type } from "arkenv";
@@ -26,14 +30,14 @@ export default type({
});
```
-#### 2. Configure for Bun.serve (dev mode)
+#### Configure for Bun.serve (dev mode)
```toml title="bunfig.toml"
[serve.static]
plugins = ["@arkenv/bun-plugin"]
```
-#### 3. Configure for Bun.build (build mode)
+#### Configure for Bun.build (build mode)
```ts title="build.ts"
import arkenv from "@arkenv/bun-plugin";
@@ -45,11 +49,35 @@ await Bun.build({
});
```
-### Advanced setup
+### 3. Add Typesafety
+
+To make `process.env` fully typesafe, see the [Typing process.env](/docs/bun-plugin/typing-process-env) guide to complete your setup.
+
+### 4. Use in your code
+
+You can now use `process.env` with full typesafety and autocompletion throughout your application.
+
+```tsx title="src/App.tsx" twoslash
+// @filename: bun-env.d.ts
+///
+type ProcessEnvAugmented = {
+ BUN_PUBLIC_API_URL: string
+}
+declare namespace NodeJS {
+ interface ProcessEnv extends ProcessEnvAugmented {}
+}
+
+// @filename: App.tsx
+// ---cut---
+const apiUrl = process.env.BUN_PUBLIC_API_URL;
+// ^?
+```
+
+## Custom schema location
If you need to customize the schema location or prefer explicit configuration:
-#### For Bun.build
+### For Bun.build
Pass your schema directly to the plugin function:
@@ -69,7 +97,7 @@ await Bun.build({
});
```
-#### For Bun.serve
+### For Bun.serve
Create a custom plugin file and reference it in `bunfig.toml`:
@@ -90,48 +118,42 @@ export default arkenv(Env);
plugins = ["./plugins/arkenv.ts"]
```
-### Using Standard Schema validators (Zod, Valibot)
+## Using Standard Schema validators (Zod, Valibot)
This plugin uses ArkType for validation, which natively supports Standard Schema. You can freely mix ArkType DSL strings with Zod or Valibot validators in the same schema - no extra configuration needed.
-```ts title="build.ts"
-import arkenv from "@arkenv/bun-plugin";
+> [!NOTE]
+> When using external validators like Zod or Valibot, you must install them separately. For example, to use the `z` symbol from `"zod"` shown below, run `npm install zod` (or use `valibot` instead).
+
+```ts title="src/env.ts" twoslash
import { type } from "arkenv";
import { z } from "zod";
-await Bun.build({
- entrypoints: ["./app.tsx"],
- outdir: "./dist",
- plugins: [
- arkenv(type({
- BUN_PUBLIC_API_URL: z.url(),
- BUN_PUBLIC_DEBUG: "boolean",
- }))
- ],
+export default type({
+ BUN_PUBLIC_API_URL: z.string().url(),
+ BUN_PUBLIC_DEBUG: "boolean",
});
```
-> [!IMPORTANT]
-> This plugin requires [ArkType](https://arktype.io) to be installed.
->
-> For a zero-ArkType setup, use [arkenv/standard](/docs/arkenv/standard) directly in your app code instead.
->
-> See [Standard Schema validators](/docs/arkenv/integrations/standard-schema) for details.
+```tsx title="src/App.tsx" twoslash
+// @filename: bun-env.d.ts
+///
+type ProcessEnvAugmented = {
+ BUN_PUBLIC_API_URL: string
+ BUN_PUBLIC_DEBUG: boolean
+}
+declare namespace NodeJS {
+ interface ProcessEnv extends ProcessEnvAugmented {}
+}
+
+// @filename: App.tsx
+// ---cut---
+const apiUrl = process.env.BUN_PUBLIC_API_URL;
+// ^?
+```
## Features
- **Static Analysis**: Automatically replaces `process.env.VARIABLE` with validated values during the build.
- **Typesafety**: Ensures your code only accesses variables defined in your schema.
-- **Secure Defaults**: Only exposes variables prefixed with `BUN_PUBLIC_` to the client bundle. `NODE_ENV` is also exposed when defined in your schema. You can customize this prefix by setting the `env` option in your `Bun.build()` configuration (e.g., `env: "MY_PUBLIC_*"` to use `MY_PUBLIC_` instead). See [Bun's bundler documentation](https://bun.sh/docs/bundler#env) for more details.
-
-## Installation
-
-```package-install
-@arkenv/bun-plugin arkenv
-```
-
-If you intend to use the default validator, you should also install `arktype`:
-
-```package-install
-arktype
-```
+- **Secure Defaults**: Only exposes variables prefixed with `BUN_PUBLIC_` to the client bundle. `NODE_ENV` is also exposed when defined in your schema. You can customize this prefix by setting the `env` option in your `Bun.build()` configuration.
diff --git a/apps/www/content/docs/bun-plugin/typing-process-env.mdx b/apps/www/content/docs/bun-plugin/typing-process-env.mdx
index 977911b7a..978956be2 100644
--- a/apps/www/content/docs/bun-plugin/typing-process-env.mdx
+++ b/apps/www/content/docs/bun-plugin/typing-process-env.mdx
@@ -9,6 +9,9 @@ With ArkEnv, this can be typesafe with the one-time setup below. After this, eac
## Setup
+> [!TIP]
+> This guide is the final step to complete the [Simple setup](/docs/bun-plugin) from the introduction page.
+
> [!IMPORTANT]
> You must have the core `arkenv` package installed as a dependency in your project. See [ArkEnv quickstart](/docs/arkenv/quickstart) for instructions.
@@ -60,7 +63,7 @@ The `ProcessEnvAugmented` type:
1. Extracts the inferred type from your schema (the result of `type()` from arkenv)
2. Filters to only include variables matching the Bun prefix (defaults to `"BUN_PUBLIC_"`) and `NODE_ENV`
-3. Makes them available on `process.env` with full type safety
+3. Makes them available on `process.env` with full typesafety
Server-only variables (like `PORT`) are automatically excluded from the client bundle and won't appear in the augmented `process.env` type.
diff --git a/apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx b/apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx
index 9dc8fa96a..ce2d4520e 100644
--- a/apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx
+++ b/apps/www/content/docs/vite-plugin/arkenv-in-viteconfig.mdx
@@ -5,13 +5,14 @@ icon: Wrench
import { Globe } from "lucide-react";
+> [!NOTE]
+> This is an **advanced setup** for when you need to access environment variables *inside* your `vite.config.ts` (e.g., to set `server.port`). For standard application usage, see the [Introduction](/docs/vite-plugin).
Vite doesn't automatically load `.env*` files when evaluating your `vite.config.ts` - those variables are only available later in your application code via `import.meta.env`. If you need environment variables in your config (like setting `server.port` or conditionally enabling plugins), you'll need to load them manually using Vite's `loadEnv` helper.
> [!IMPORTANT]
> You must have the core `arkenv` package installed as a dependency in your project. See [ArkEnv quickstart](/docs/arkenv/quickstart) for instructions.
-
Here's how to validate those variables with ArkEnv. The key is defining your schema *once* with ArkEnv's `type()` and reusing it for both server-side config variables and client-exposed `VITE_*` variables:
```ts title="vite.config.ts" twoslash
diff --git a/apps/www/content/docs/vite-plugin/index.mdx b/apps/www/content/docs/vite-plugin/index.mdx
index de5062699..3bed97b07 100644
--- a/apps/www/content/docs/vite-plugin/index.mdx
+++ b/apps/www/content/docs/vite-plugin/index.mdx
@@ -1,26 +1,78 @@
---
title: Introduction
icon: Album
+description: The ArkEnv plugin for Vite lets you validate environment variables at build-time with ArkType.
---
-## What is this?
+> [!IMPORTANT]
+> This plugin requires [ArkType](https://arktype.io) to be installed.
+
+## Quickstart
-The ArkEnv plugin for Vite lets you validate environment variables at build-time with ArkEnv.
+### 1. Installation
+
+```package-install
+@arkenv/vite-plugin arkenv
+```
+
+### 2. Configure Plugin
+
+Define your schema as an exported constant in `vite.config.ts`. This allows the schema to be imported for typesafety in other files.
```ts title="vite.config.ts" twoslash
import arkenv from "@arkenv/vite-plugin";
+import { type } from "arkenv";
import { defineConfig } from "vite";
+export const Env = type({
+ PORT: "number.port",
+ VITE_MY_VAR: "string"
+});
+
export default defineConfig({
- plugins: [
- arkenv({
- PORT: "number.port",
- VITE_MY_VAR: "string",
- }),
- ],
+ plugins: [arkenv(Env)]
});
```
+### 3. Add Typesafety
+
+To make `import.meta.env` fully typesafe, add the following to `src/vite-env.d.ts`:
+
+```ts title="src/vite-env.d.ts"
+///
+
+type ImportMetaEnvAugmented = import("@arkenv/vite-plugin").ImportMetaEnvAugmented<
+ typeof import("../vite.config").Env
+>;
+
+interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
+```
+
+### 4. Use in your code
+
+You can now use `import.meta.env` with full typesafety and autocompletion throughout your application.
+
+```tsx title="src/App.tsx" twoslash
+// @filename: vite-env.d.ts
+///
+type ImportMetaEnvAugmented = {
+ VITE_MY_VAR: string
+}
+interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
+
+// @filename: App.tsx
+// ---cut---
+const apiUrl = import.meta.env.VITE_MY_VAR;
+// ^?
+```
+
With this setup, if any environment variable is missing or invalid, your dev server won't start and your production build will fail with an error:
```bash title="Terminal"
@@ -29,43 +81,56 @@ ArkEnvError: Errors found while validating environment variables
PORT must be an integer between 0 and 65535 (was "hello")
```
+> [!TIP]
+> For more details on advanced typing options, see [Typing import.meta.env](/docs/vite-plugin/typing-import-meta-env).
+
## Using Standard Schema validators (Zod, Valibot)
This plugin uses ArkType for validation, which natively supports Standard Schema. You can freely mix ArkType DSL strings with Zod or Valibot validators in the same schema - no extra configuration needed.
-```ts title="vite.config.ts"
-import { defineConfig } from "vite";
+> [!NOTE]
+> When using Standard Schema validators, you must install the validator package separately. For example, the code below imports `z` from `"zod"` and uses `type({ ... })` with Zod validators - install with `npm install zod` (or use `valibot` instead).
+
+```ts title="vite.config.ts" twoslash
import arkenv from "@arkenv/vite-plugin";
+import { type } from "arkenv";
+import { defineConfig } from "vite";
import { z } from "zod";
+export const Env = type({
+ VITE_API_URL: z.string().url(),
+ VITE_API_KEY: z.string().min(1),
+ VITE_DEBUG: "boolean"
+});
+
export default defineConfig({
- plugins: [
- arkenv({
- VITE_API_URL: z.url(),
- VITE_API_KEY: z.string().min(1),
- VITE_DEBUG: "boolean",
- }),
- ],
+ plugins: [arkenv(Env)]
});
```
-> [!IMPORTANT]
-> This plugin requires [ArkType](https://arktype.io) to be installed.
->
-> For a zero-ArkType setup, use [arkenv/standard](/docs/arkenv/standard) directly in your app code instead.
->
-> See [Standard Schema validators](/docs/arkenv/integrations/standard-schema) for details.
-
-## Installation
-
-```package-install
-@arkenv/vite-plugin
+```tsx title="src/App.tsx" twoslash
+// @filename: vite-env.d.ts
+///
+type ImportMetaEnvAugmented = {
+ VITE_API_URL: string
+ VITE_API_KEY: string
+ VITE_DEBUG: boolean
+}
+interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+interface ImportMeta {
+ readonly env: ImportMetaEnv
+}
+
+// @filename: App.tsx
+// ---cut---
+const apiUrl = import.meta.env.VITE_API_URL;
+// ^?
```
-If you intend to use `arkenv` (requires ArkType), also install `arktype`:
+For advanced workflows, see [using ArkEnv in Vite config](/docs/vite-plugin/arkenv-in-viteconfig).
-```package-install
-arktype
-```
+## Features
-For some workflows (including [using ArkEnv in Vite config](/docs/vite-plugin/arkenv-in-viteconfig) and [typing import.meta.env](/docs/vite-plugin/typing-import-meta-env)), a dedicated `arkenv` installation is needed. See [ArkEnv quickstart](/docs/arkenv/quickstart) for more instructions.
+- **Static Analysis**: Automatically replaces `import.meta.env.VARIABLE` with validated values during the build.
+- **Typesafety**: Ensures your code only accesses variables defined in your schema.
+- **Secure Defaults**: Only exposes variables prefixed with `VITE_` to the client bundle. `NODE_ENV` is also exposed when defined in your schema.
diff --git a/apps/www/content/docs/vite-plugin/meta.json b/apps/www/content/docs/vite-plugin/meta.json
index ec0359d21..758fd95e1 100644
--- a/apps/www/content/docs/vite-plugin/meta.json
+++ b/apps/www/content/docs/vite-plugin/meta.json
@@ -6,7 +6,7 @@
"pages": [
"---Guide---",
"index",
- "arkenv-in-viteconfig",
- "typing-import-meta-env"
+ "typing-import-meta-env",
+ "arkenv-in-viteconfig"
]
}
diff --git a/apps/www/content/docs/vite-plugin/typing-import-meta-env.mdx b/apps/www/content/docs/vite-plugin/typing-import-meta-env.mdx
index c4ef5f6c7..6ba9027a3 100644
--- a/apps/www/content/docs/vite-plugin/typing-import-meta-env.mdx
+++ b/apps/www/content/docs/vite-plugin/typing-import-meta-env.mdx
@@ -12,7 +12,6 @@ With ArkEnv, this can be typesafe with the one-time setup below. After this, eac
> [!IMPORTANT]
> You must have the core `arkenv` package installed as a dependency in your project. See [ArkEnv quickstart](/docs/arkenv/quickstart) for instructions.
-
Add this to a `vite-env.d.ts` file in your `src` directory:
```ts title="src/vite-env.d.ts"
@@ -23,19 +22,25 @@ type ImportMetaEnvAugmented =
typeof import("../vite.config").Env
>;
+// Augment import.meta.env with your schema
+// Only `VITE_*` prefixed variables will be included
+interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
+
interface ViteTypeOptions {
- // By adding this line, you can make the type of ImportMetaEnv strict
- // to disallow unknown keys.
+ // Optional: disallow unknown keys in import.meta.env
// See: https://vite.dev/guide/env-and-mode#intellisense-for-typescript
// ⚠️ This option requires Vite 6.3.x or higher
strictImportMetaEnv: unknown;
}
-
-// Augment import.meta.env with your schema
-// Only `VITE_*` prefixed variables will be included
-interface ImportMetaEnv extends ImportMetaEnvAugmented {}
```
+> [!NOTE]
+> The `interface ImportMeta` block is required in some TypeScript configurations to ensure that the augmented `ImportMetaEnv` is correctly recognized on `import.meta.env`.
+
## Usage
Once set up, `import.meta.env` is fully typesafe:
@@ -55,7 +60,7 @@ The `ImportMetaEnvAugmented` type:
1. Extracts the inferred type from your schema (the result of `type()` from arkenv)
2. Filters to only include variables matching the Vite prefix (defaults to `"VITE_"`)
-3. Makes them available on `import.meta.env` with full type safety
+3. Makes them available on `import.meta.env` with full typesafety
Server-only variables (like `PORT`) are automatically excluded from the client bundle and won't appear in `import.meta.env`.
@@ -97,11 +102,15 @@ type ImportMetaEnvAugmented =
typeof import("./env").Env
>;
+interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
+
interface ViteTypeOptions {
strictImportMetaEnv: unknown;
}
-
-interface ImportMetaEnv extends ImportMetaEnvAugmented {}
```
> [!IMPORTANT]
diff --git a/apps/www/lib/twoslash-options.ts b/apps/www/lib/twoslash-options.ts
index 0e5474a23..9ff314bd3 100644
--- a/apps/www/lib/twoslash-options.ts
+++ b/apps/www/lib/twoslash-options.ts
@@ -25,7 +25,7 @@ export type ArkTypeTwoslashOptions = TransformerTwoslashOptions & {
export const arktypeTwoslashOptions: ArkTypeTwoslashOptions = {
explicitTrigger: true,
- langs: ["ts", "js"],
+ langs: ["ts", "tsx", "js", "jsx"],
twoslashOptions: {
compilerOptions: {
paths: {
diff --git a/apps/www/source.config.ts b/apps/www/source.config.ts
index 152e8618c..e0c0ede41 100644
--- a/apps/www/source.config.ts
+++ b/apps/www/source.config.ts
@@ -22,7 +22,7 @@ export default defineConfig({
rehypePlugins: [rehypeGithubAlerts, rehypeOptimizeInternalLinks],
remarkPlugins: [remarkGemoji, remarkNpm, remarkDirective],
rehypeCodeOptions: {
- langs: ["ts", "js", "json", "bash", "dotenv"],
+ langs: ["ts", "tsx", "js", "jsx", "json", "bash", "dotenv"],
themes: {
light: "github-light-high-contrast",
dark: "github-dark-high-contrast",
diff --git a/examples/with-bun-react/bun.lock b/examples/with-bun-react/bun.lock
index faff22b2e..08177c51d 100644
--- a/examples/with-bun-react/bun.lock
+++ b/examples/with-bun-react/bun.lock
@@ -12,7 +12,7 @@
"react-dom": "^19.2.5",
},
"devDependencies": {
- "@types/bun": "^1.3.12",
+ "@types/bun": "^1.3.13",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"rimraf": "^6.1.3",
@@ -50,7 +50,7 @@
"@oven/bun-windows-x64-baseline": ["@oven/bun-windows-x64-baseline@1.3.13", "", { "os": "win32", "cpu": "x64" }, "sha512-6gy4hhQSjq/T/S9hC9m3NxY0RY+9Ww+XNlB+8koIMTsMSYEjk7Ho+hFHQz1Bn4W61Ub7Vykufg+jgDgPfa2GFA=="],
- "@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="],
+ "@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="],
"@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
@@ -70,7 +70,7 @@
"bun": ["bun@1.3.13", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.13", "@oven/bun-darwin-x64": "1.3.13", "@oven/bun-darwin-x64-baseline": "1.3.13", "@oven/bun-linux-aarch64": "1.3.13", "@oven/bun-linux-aarch64-musl": "1.3.13", "@oven/bun-linux-x64": "1.3.13", "@oven/bun-linux-x64-baseline": "1.3.13", "@oven/bun-linux-x64-musl": "1.3.13", "@oven/bun-linux-x64-musl-baseline": "1.3.13", "@oven/bun-windows-aarch64": "1.3.13", "@oven/bun-windows-x64": "1.3.13", "@oven/bun-windows-x64-baseline": "1.3.13" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-b9T4xZ8KqCHs4+TkHJv540LG1B8OD7noKu0Qaizusx3jFtMDHY6osNqgbaOlwW2B8RB2AKzz+sjzlGKIGxIjZw=="],
- "bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="],
+ "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="],
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
diff --git a/examples/with-bun/bun.lock b/examples/with-bun/bun.lock
index d9541e51d..986fe9402 100644
--- a/examples/with-bun/bun.lock
+++ b/examples/with-bun/bun.lock
@@ -9,7 +9,7 @@
"arktype": "^2.2.0",
},
"devDependencies": {
- "@types/bun": "^1.3.12",
+ "@types/bun": "^1.3.13",
"rimraf": "^6.1.3",
"typescript": "^6.0.3",
},
@@ -20,7 +20,7 @@
"@ark/util": ["@ark/util@0.56.0", "", {}, "sha512-BghfRC8b9pNs3vBoDJhcta0/c1J1rsoS1+HgVUreMFPdhz/CRAKReAu57YEllNaSy98rWAdY1gE+gFup7OXpgA=="],
- "@types/bun": ["@types/bun@1.3.12", "", { "dependencies": { "bun-types": "1.3.12" } }, "sha512-DBv81elK+/VSwXHDlnH3Qduw+KxkTIWi7TXkAeh24zpi5l0B2kUg9Ga3tb4nJaPcOFswflgi/yAvMVBPrxMB+A=="],
+ "@types/bun": ["@types/bun@1.3.13", "", { "dependencies": { "bun-types": "1.3.13" } }, "sha512-9fqXWk5YIHGGnUau9TEi+qdlTYDAnOj+xLCmSTwXfAIqXr2x4tytJb43E9uCvt09zJURKXwAtkoH4nLQfzeTXw=="],
"@types/node": ["@types/node@25.6.0", "", { "dependencies": { "undici-types": "~7.19.0" } }, "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ=="],
@@ -34,7 +34,7 @@
"brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
- "bun-types": ["bun-types@1.3.12", "", { "dependencies": { "@types/node": "*" } }, "sha512-HqOLj5PoFajAQciOMRiIZGNoKxDJSr6qigAttOX40vJuSp6DN/CxWp9s3C1Xwm4oH7ybueITwiaOcWXoYVoRkA=="],
+ "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="],
"glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
diff --git a/examples/with-vite-react/README.md b/examples/with-vite-react/README.md
index 38ec30d35..e5b0dcbff 100644
--- a/examples/with-vite-react/README.md
+++ b/examples/with-vite-react/README.md
@@ -115,6 +115,6 @@ For more information, see the [@arkenv/vite-plugin documentation](https://arkenv
2. **Automatic Filtering**: The plugin automatically filters the schema to only expose `VITE_*` prefixed variables to the client, preventing server-only variables from leaking into the bundle.
-3. **Type Safety**: With the `vite-env.d.ts` setup, `import.meta.env` is fully typesafe with autocomplete and type checking.
+3. **Typesafety**: With the `vite-env.d.ts` setup, `import.meta.env` is fully typesafe with autocomplete and type checking.
4. **Build-Time Validation**: Missing or invalid environment variables will cause the dev server to fail to start and production builds to fail with clear error messages.
diff --git a/examples/with-vite-react/src/vite-env.d.ts b/examples/with-vite-react/src/vite-env.d.ts
index 05a012746..58f46eef3 100644
--- a/examples/with-vite-react/src/vite-env.d.ts
+++ b/examples/with-vite-react/src/vite-env.d.ts
@@ -19,3 +19,7 @@ interface ViteTypeOptions {
// Now import.meta.env is totally typesafe and based on your `Env` schema definition
// Only VITE_* prefixed variables will be included (PORT is excluded)
interface ImportMetaEnv extends ImportMetaEnvAugmented {}
+
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
diff --git a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/design.md b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/design.md
index a341c120c..cc712c024 100644
--- a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/design.md
+++ b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/design.md
@@ -8,7 +8,7 @@ Users need to validate unprefixed environment variables (e.g., `PORT`, database
### Goals
- Allow schema to be defined once and reused in both contexts
-- Maintain type safety in both contexts
+- Maintain typesafety in both contexts
- Follow the spec requirement that schemas must be defined using `type()` function
- Avoid code duplication
@@ -27,7 +27,7 @@ Users need to validate unprefixed environment variables (e.g., `PORT`, database
- Simplest solution that meets all requirements
- Follows the spec requirement that schemas must be defined using `type()`
- Avoids code duplication
-- Maintains type safety in both contexts
+- Maintains typesafety in both contexts
- No need for additional wrapper utilities
**Alternatives considered**:
diff --git a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/proposal.md b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/proposal.md
index 053d2b9d0..5a643ba22 100644
--- a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/proposal.md
+++ b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/proposal.md
@@ -7,7 +7,7 @@ There's no clear documentation on how to use ArkEnv for non-prefixed environment
This creates a gap where:
- Users might manually access `process.env` in vite.config.ts without validation
- Configuration errors are discovered late (at runtime) rather than at build-time
-- No type safety for environment variables used in Vite config
+- No typesafety for environment variables used in Vite config
- Confusion between server-only (config) and client-exposed (`VITE_*`) environment usage
**Related Issue**: [#365](https://github.com/yamcodes/arkenv/issues/365)
@@ -69,7 +69,7 @@ This change focuses on:
- Documentation files (README, docs)
- Example vite.config.ts files
- Potentially `@arkenv/vite-plugin` if we add a `loadEnv` wrapper utility
-- **User-facing**: Users can now validate unprefixed environment variables in vite.config.ts with full type safety
+- **User-facing**: Users can now validate unprefixed environment variables in vite.config.ts with full typesafety
## References
diff --git a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/specs/vite-config-usage/spec.md b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/specs/vite-config-usage/spec.md
index 1d1f50fd7..37bc1ac88 100644
--- a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/specs/vite-config-usage/spec.md
+++ b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/specs/vite-config-usage/spec.md
@@ -37,7 +37,7 @@ The schema SHALL be defined using ArkType's `type()` function (not as a raw obje
- **AND** they define the schema using `type()` outside of `defineConfig`
- **THEN** the schema can be defined once and used in both places
- **AND** TypeScript types are available in both contexts
-- **AND** the solution avoids code duplication and maintains type safety
+- **AND** the solution avoids code duplication and maintains typesafety
- **AND** `createEnv()` and the Vite plugin accept the type definition directly
### Requirement: loadEnv Wrapper Utility
@@ -52,7 +52,7 @@ The project SHALL support using ArkEnv with Vite's `loadEnv` function. Since `cr
- **AND** the same type definition can be passed to the Vite plugin for validating `VITE_*` variables
- **AND** no separate wrapper utility is needed
-### Requirement: Type Safety Constraint
+### Requirement: Typesafety Constraint
The environment object returned from `loadEnv` or any wrapper SHALL be typesafe. Unsafe patterns that bypass validation or type checking are FORBIDDEN.
@@ -68,7 +68,7 @@ The environment object returned from `loadEnv` or any wrapper SHALL be typesafe.
- **OR** a user attempts to use `as const` assertion on an environment object
- **THEN** the pattern is documented as forbidden
- **AND** examples demonstrate only typesafe patterns
-- **AND** documentation clearly explains why unsafe patterns (including `as const`) are not allowed and do not provide type safety
+- **AND** documentation clearly explains why unsafe patterns (including `as const`) are not allowed and do not provide typesafety
### Requirement: Documentation for Vite Config Usage
@@ -86,5 +86,5 @@ The project SHALL provide clear documentation and examples for using ArkEnv in v
- **THEN** they see an example of using ArkEnv with `loadEnv` in vite.config.ts
- **AND** the example demonstrates validating unprefixed variables for config use
- **AND** the example is clear and follows best practices
-- **AND** the example demonstrates both validation and type safety
+- **AND** the example demonstrates both validation and typesafety
diff --git a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/tasks.md b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/tasks.md
index a88c48210..2f11b01de 100644
--- a/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/tasks.md
+++ b/openspec/changes/archive/2025-11-20-add-arkenv-vite-config/tasks.md
@@ -47,8 +47,8 @@
- Tests verify `createEnv` works with type definitions and custom environments (simulating loadEnv)
- [x] 4.2 Test error handling when config env vars are invalid
- Tests verify error handling with type definitions
-- [x] 4.3 Verify type safety in vite.config.ts examples
- - Type safety verified through TypeScript compilation and tests
+- [x] 4.3 Verify typesafety in vite.config.ts examples
+ - Typesafety verified through TypeScript compilation and tests
- [x] 4.4 Test the loadEnv wrapper utility (if implemented)
- Not needed - `createEnv` directly accepts type definitions
diff --git a/openspec/changes/archive/2025-11-20-fix-vite-plugin-env-filter/design.md b/openspec/changes/archive/2025-11-20-fix-vite-plugin-env-filter/design.md
index 82b8d5f7c..ed7af01d9 100644
--- a/openspec/changes/archive/2025-11-20-fix-vite-plugin-env-filter/design.md
+++ b/openspec/changes/archive/2025-11-20-fix-vite-plugin-env-filter/design.md
@@ -63,7 +63,7 @@ Vite has a built-in convention where only environment variables prefixed with `V
- **Performance**: Overhead is minimal for typical schemas (most schemas have < 20 variables)
**Alternative considered**:
-- **Filter schema, then validate**: Would require complex schema manipulation to handle both raw schemas and `type()` definitions, potentially losing type information. Also provides less validation coverage since server-only variables wouldn't be validated in the plugin context. The complexity and type safety concerns outweigh the minor performance benefit.
+- **Filter schema, then validate**: Would require complex schema manipulation to handle both raw schemas and `type()` definitions, potentially losing type information. Also provides less validation coverage since server-only variables wouldn't be validated in the plugin context. The complexity and typesafety concerns outweigh the minor performance benefit.
## Risks / Trade-offs
diff --git a/openspec/changes/archive/2025-11-28-add-bun-plugin/design.md b/openspec/changes/archive/2025-11-28-add-bun-plugin/design.md
index 3ffff2123..6f6e4512c 100644
--- a/openspec/changes/archive/2025-11-28-add-bun-plugin/design.md
+++ b/openspec/changes/archive/2025-11-28-add-bun-plugin/design.md
@@ -132,7 +132,7 @@ This keeps the default experience zero-config for most users, while still allowi
#### Alternatives considered
- **Static file reference as the only pattern** (previous design): Forces every project to create a separate `bun-plugin-config.ts` file even in simple setups, increasing boilerplate.
-- **Schema definition via JSON/YAML or bunfig.toml**: Reduces type safety and breaks the “define once in TypeScript” story that ArkEnv aims for.
+- **Schema definition via JSON/YAML or bunfig.toml**: Reduces typesafety and breaks the “define once in TypeScript” story that ArkEnv aims for.
- **Only programmatic configuration** (no bunfig path): Would make full-stack `Bun.serve()` setups awkward compared to other Bun plugins that integrate via `bunfig.toml`.
diff --git a/openspec/changes/archive/2025-11-28-add-bun-plugin/proposal.md b/openspec/changes/archive/2025-11-28-add-bun-plugin/proposal.md
index 59e83eedc..1a0f21fce 100644
--- a/openspec/changes/archive/2025-11-28-add-bun-plugin/proposal.md
+++ b/openspec/changes/archive/2025-11-28-add-bun-plugin/proposal.md
@@ -132,7 +132,7 @@ This keeps the default experience zero-config for most users, while still allowi
**Alternatives considered**:
- **Static file reference as the only pattern** (previous design): Forces every project to create a separate `bun-plugin-config.ts` file even in simple setups, increasing boilerplate.
-- **Schema definition via JSON/YAML or bunfig.toml**: Reduces type safety and breaks the “define once in TypeScript” story that ArkEnv aims for.
+- **Schema definition via JSON/YAML or bunfig.toml**: Reduces typesafety and breaks the “define once in TypeScript” story that ArkEnv aims for.
- **Only programmatic configuration** (no bunfig path): Would make full-stack `Bun.serve()` setups awkward compared to other Bun plugins that integrate via `bunfig.toml`.
@@ -149,7 +149,7 @@ Bun's bundler statically replaces `process.env` variables during build, which me
- Type augmentation is needed for type-safe access to `process.env` in client code
- The plugin must work within Bun's serve function for full-stack React apps
-Without a Bun plugin, users must manually validate environment variables or risk runtime errors, and they lose the type safety and build-time validation benefits that ArkEnv provides.
+Without a Bun plugin, users must manually validate environment variables or risk runtime errors, and they lose the typesafety and build-time validation benefits that ArkEnv provides.
## What Changes
diff --git a/openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md b/openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
index e526dcbb4..9610ef31a 100644
--- a/openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
+++ b/openspec/changes/archive/2025-12-22-coercion-public-api/proposal.md
@@ -19,7 +19,7 @@ Instead of inspecting proprietary ArkType structures (`schema.in.json`) or mutat
## Impact
- **Reliability**: Relies on a stable external standard (JSON Schema) rather than ArkType's fluctuating internal representation.
-- **Type Safety**: `toJsonSchema()` returns a strictly typed `JsonSchema` interface, whereas `in.json` returns loose `JsonStructure` types requiring unsafe assertions.
+- **Typesafety**: `toJsonSchema()` returns a strictly typed `JsonSchema` interface, whereas `in.json` returns loose `JsonStructure` types requiring unsafe assertions.
- **Performance**: Introspection happens once; the pre-processing morph is a simple object traversal.
- **Consistency**: Retains 100% compatibility with existing coercion behavior.
@@ -29,7 +29,7 @@ Instead of inspecting proprietary ArkType structures (`schema.in.json`) or mutat
- **Limit**: Strictly enforce < 200 lines per file. Use `utils/coercion/` directory for modularization if required.
- **Internal Sharing**: Any logic shared across packages must reside in `packages/internal/`.
-### Strict Type Safety
+### Strict Typesafety
- **Standard API only**: Use `schema.in.toJsonSchema()` for all introspection.
- **No Prop probing**: Do not probe for `domain`, `unit`, or `branches` on generic objects.
- **Avoid Assertions**: Use discriminated unions provided by the `JsonSchema` type definition.
diff --git a/openspec/changes/archive/2026-01-21-fix-standard-mode-inference/proposal.md b/openspec/changes/archive/2026-01-21-fix-standard-mode-inference/proposal.md
index 135cd4590..336e25377 100644
--- a/openspec/changes/archive/2026-01-21-fix-standard-mode-inference/proposal.md
+++ b/openspec/changes/archive/2026-01-21-fix-standard-mode-inference/proposal.md
@@ -29,4 +29,4 @@ We already have `packages/internal/types/src/standard-schema.ts`. We will use th
- Introducing complex auto-detection of schemas (we stick to the explicit `validator` flag).
## Design Principle
-**Type Safety without Vendor Lock-in.** ArkEnv should provide first-class type safety for both ArkType and Standard Schema users, respecting the inference rules of each.
+**Typesafety without Vendor Lock-in.** ArkEnv should provide first-class typesafety for both ArkType and Standard Schema users, respecting the inference rules of each.
diff --git a/openspec/changes/improve-plugin-docs/design.md b/openspec/changes/improve-plugin-docs/design.md
new file mode 100644
index 000000000..73ab9fffb
--- /dev/null
+++ b/openspec/changes/improve-plugin-docs/design.md
@@ -0,0 +1,113 @@
+# Design: Improve Plugin Docs
+
+## Overview
+
+This is a documentation-only change. No package source code or types are modified. All changes are in `apps/www/content/docs/`.
+
+## Vite Plugin Documentation
+
+### Problem Diagnosis
+
+The root issue is a **mismatch between the intro page and the typing page**:
+
+- **Intro page** (`index.mdx`): Shows `arkenv({ PORT: "number.port", VITE_MY_VAR: "string" })` — the schema is passed inline and not exported.
+- **Typing page** (`typing-import-meta-env.mdx`): Requires `typeof import("../vite.config").Env` — but `Env` is never exported on the intro page.
+
+A user following the docs in order ends up with:
+1. A working dev server (plugin validates envs ✅)
+2. But `import.meta.env.VITE_MY_VAR` is not typed (❌) because the `vite-env.d.ts` can't import `Env`.
+
+Additionally, the `vite-env.d.ts` block in the docs is missing:
+```ts
+interface ImportMeta {
+ readonly env: ImportMetaEnv;
+}
+```
+Some Vite/TS setups need this for the augmentation to take effect.
+
+### New Flow
+
+The standard setup will be **a single, linear progression**:
+
+1. **Install** (unchanged)
+2. **Define your schema as an exported constant** in `vite.config.ts`
+3. **Copy the `vite-env.d.ts` snippet** — complete, including `interface ImportMeta`
+4. Done — `import.meta.env.VITE_*` is fully typed
+
+"Using ArkEnv in Vite config" (loadEnv) remains a separate page but is clearly marked as the advanced/optional use case.
+
+### File-by-File Changes
+
+#### `content/docs/vite-plugin/index.mdx`
+
+- Lead with a concrete "Quickstart" that covers both validation AND typing in one place
+- First code block: show `vite.config.ts` with `export const Env = type({...})` and `arkenv(Env)`
+- Second code block: show the complete `src/vite-env.d.ts` snippet right on the intro page as "Step 2"
+- Keep the error output block to show the fail-fast benefit
+- Keep Standard Schema section (unchanged)
+- Keep Installation section (moved to the end)
+- Remove the confusing footnote about "some workflows require a dedicated arkenv installation"
+
+#### `content/docs/vite-plugin/typing-import-meta-env.mdx`
+
+- Update the `vite-env.d.ts` snippet to include the `interface ImportMeta` block
+- Add a note explaining that the `ImportMeta` interface is required for some Vite/TS setups
+- Clarify that `ViteTypeOptions.strictImportMetaEnv` requires Vite ≥ 6.3 and is optional
+- The "As your project grows" section stays — it correctly shows the dedicated `src/env.ts` pattern
+
+#### `content/docs/vite-plugin/arkenv-in-viteconfig.mdx`
+
+- Add a clear preamble: "This is an advanced setup for when you need environment variables _inside_ your Vite config itself (e.g., to set `server.port`). Most projects don't need this."
+- No other structural changes needed
+
+#### `content/docs/vite-plugin/meta.json`
+
+Reorder pages so typing comes before arkenv-in-viteconfig:
+```json
+{
+ "pages": [
+ "---Guide---",
+ "index",
+ "typing-import-meta-env",
+ "arkenv-in-viteconfig"
+ ]
+}
+```
+
+---
+
+## Bun Plugin Documentation
+
+### Problem Diagnosis
+
+The Bun plugin has the same structural issue: the "simple setup" creates an anonymous default export, while the `typing-process-env` page needs to reference it. However, since the bun plugin's simple setup uses `export default type({...})` (not a named constant), the typing page correctly references `typeof import("./src/env").default` — this actually works.
+
+The main issues are:
+1. The flow doesn't make it obvious that typing is the "normal" thing to do, not an afterthought
+2. The intro page is very long and mixes simple + advanced + Standard Schema all in one page
+
+### File-by-File Changes
+
+#### `content/docs/bun-plugin/index.mdx`
+
+- Add a brief intro paragraph explaining that the standard setup gives you both validation AND typed `process.env`
+- After step 1 (schema), add a callout: "See [Typing process.env](/docs/bun-plugin/typing-process-env) to complete the setup"
+- Rename "Advanced setup" heading to make the distinction clearer: "Custom schema location"
+
+#### `content/docs/bun-plugin/typing-process-env.mdx`
+
+- No structural changes needed — the snippet is complete
+- Add a small note clarifying that this is the recommended step 4 after the intro setup
+
+#### `content/docs/bun-plugin/meta.json`
+
+- No reordering needed — `typing-process-env` already follows `index`
+
+---
+
+## Non-Goals
+
+- No changes to package source code
+- No changes to type exports (`ImportMetaEnvAugmented`, `ProcessEnvAugmented`)
+- No changes to the `arkenv` core docs or quickstart
+- Not adding a third page to either plugin's docs section
diff --git a/openspec/changes/improve-plugin-docs/proposal.md b/openspec/changes/improve-plugin-docs/proposal.md
new file mode 100644
index 000000000..d5246a4a5
--- /dev/null
+++ b/openspec/changes/improve-plugin-docs/proposal.md
@@ -0,0 +1,35 @@
+# Change: Improve Plugin Docs
+
+## Why
+
+The current plugin documentation is unclear and leaves users without a working, typesafe `import.meta.env` (for Vite) or `process.env` (for Bun) setup by default. Real-world testing revealed two specific pain points:
+
+1. **Missing `Env` export from `vite.config.ts`**: The Vite plugin's introduction page shows the plugin being used inline (`arkenv({ VITE_MY_VAR: "string" })`) without exporting the schema as a named `Env` constant. The `typing-import-meta-env` page then requires `typeof import("../vite.config").Env`, but there's no `Env` to import — the inline schema is anonymous. Users following the intro then switching to the typing page end up with a broken setup.
+
+2. **`vite-env.d.ts` missing `interface ImportMeta`**: The documented `vite-env.d.ts` block omits the `interface ImportMeta { readonly env: ImportMetaEnv; }` declaration that some Vite setups require for the augmentation to take effect. Users on older Vite versions or certain TypeScript configs can end up with `import.meta.env.VITE_MY_ENV` silently untyped.
+
+3. **Wrong information hierarchy**: Typing `import.meta.env` / `process.env` is the primary value proposition of these plugins, yet it is currently placed _after_ the intro page and framed as a follow-up step. Using envs _in the config itself_ (loading them via `loadEnv`) is the genuinely advanced use case and should be labelled as such.
+
+4. **Bun plugin docs have parallel issues**: The structure and flow mirror the Vite plugin docs, so the same confusions apply there too.
+
+## What Changes
+
+- **Vite plugin — Introduction page**: Rewrite so the very first example exports `Env` as a named constant and passes it to the plugin. The schema should not be inline/anonymous in the intro.
+- **Vite plugin — Introduction page**: Integrate a concise "Typing `import.meta.env`" section directly into the intro (or link to it prominently as step 2), making it part of the standard setup, not a footnote.
+- **Vite plugin — `typing-import-meta-env` page**: Add the missing `interface ImportMeta` block to the `vite-env.d.ts` example. Add a clear note explaining why it's needed.
+- **Vite plugin — `arkenv-in-viteconfig` page**: Rename or relabel to make it clearly "advanced". Move it to the bottom of the sidebar or wrap its content in an `` / note.
+- **Vite plugin — `meta.json`**: Reorder sidebar pages so typing comes before the advanced config page.
+- **Bun plugin — Introduction page**: Apply parallel improvements — exported schema constant in the first example, typing `process.env` foregrounded as the standard setup.
+- **Bun plugin — `typing-process-env` page**: Verify the code sample is complete and unambiguous.
+
+## Impact
+
+- **Affected docs**: `content/docs/vite-plugin/index.mdx`, `content/docs/vite-plugin/typing-import-meta-env.mdx`, `content/docs/vite-plugin/arkenv-in-viteconfig.mdx`, `content/docs/vite-plugin/meta.json`, `content/docs/bun-plugin/index.mdx`, `content/docs/bun-plugin/typing-process-env.mdx`, `content/docs/bun-plugin/meta.json`
+- **No code changes**: This is a documentation-only change. No package source files or types are modified.
+- **User-facing**: New users get a working, fully typed setup out of the box without having to read multiple pages and assemble the pieces.
+
+## References
+
+- Vite: [TypeScript for client-side env vars](https://vite.dev/guide/env-and-mode#intellisense-for-typescript)
+- Vite: [Strict `ImportMetaEnv`](https://vite.dev/guide/env-and-mode#intellisense-for-typescript) (`ViteTypeOptions.strictImportMetaEnv`)
+- Bun: [Environment variables](https://bun.sh/docs/runtime/env)
diff --git a/openspec/changes/improve-plugin-docs/tasks.md b/openspec/changes/improve-plugin-docs/tasks.md
new file mode 100644
index 000000000..19336e08d
--- /dev/null
+++ b/openspec/changes/improve-plugin-docs/tasks.md
@@ -0,0 +1,43 @@
+## 1. Vite Plugin — Introduction Page (`index.mdx`)
+
+- [x] 1.1 Replace the inline plugin call with `export const Env = type({...})` exported constant pattern
+- [x] 1.2 Add "Step 2" section inline on the intro page showing the complete `src/vite-env.d.ts` snippet (including `interface ImportMeta`)
+- [x] 1.3 Keep error output block and Standard Schema section
+- [x] 1.4 Move Installation section to the top of Quickstart
+
+## 2. Vite Plugin — Typing Page (`typing-import-meta-env.mdx`)
+
+- [x] 2.1 Add `interface ImportMeta { readonly env: ImportMetaEnv; }` to the `vite-env.d.ts` code block
+- [x] 2.2 Add a note explaining when/why `interface ImportMeta` is needed
+- [x] 2.3 Clarify that `ViteTypeOptions.strictImportMetaEnv` is optional and requires Vite ≥ 6.3
+
+## 3. Vite Plugin — Advanced Config Page (`arkenv-in-viteconfig.mdx`)
+
+- [x] 3.1 Add a clear "advanced/optional" preamble at the top of the page
+
+## 4. Vite Plugin — Sidebar Order (`meta.json`)
+
+- [x] 4.1 Move `typing-import-meta-env` before `arkenv-in-viteconfig` in the pages array
+
+## 5. Bun Plugin — Introduction Page (`index.mdx`)
+
+- [x] 5.1 Add a brief intro paragraph clarifying that completing the setup gives you typed `process.env`
+- [x] 5.2 After "Create your schema" step, add a callout pointing to the typing page
+- [x] 5.3 Rename "Advanced setup" heading to "Custom schema location" for clarity
+- [x] 5.4 Move Installation section to the top of Usage
+
+## 6. Bun Plugin — Typing Page (`typing-process-env.mdx`)
+
+- [x] 6.1 Add a note that this is the recommended completion of the setup from the intro page
+
+## 7. Playgrounds
+
+- [x] 7.1 Update `apps/playgrounds/vite/src/vite-env.d.ts` to include `interface ImportMeta` block
+- [x] 7.2 Update `apps/playgrounds/vite-legacy/src/vite-env.d.ts` (if it exists) to match
+
+## 8. Verification
+
+- [ ] 8.1 Open the docs site locally (`pnpm dev` in `apps/www`) and visually verify the Vite plugin pages
+- [ ] 8.2 Verify the Bun plugin pages look correct
+- [ ] 8.3 Confirm the sidebar order is correct for both plugins
+- [ ] 8.4 Test the `vite-env.d.ts` snippet in the test Vite app to confirm typing works end-to-end
diff --git a/openspec/changes/improve-plugin-docs/walkthrough.md b/openspec/changes/improve-plugin-docs/walkthrough.md
new file mode 100644
index 000000000..2cad9edff
--- /dev/null
+++ b/openspec/changes/improve-plugin-docs/walkthrough.md
@@ -0,0 +1,40 @@
+# Walkthrough: Improved Plugin Documentation
+
+I have improved the documentation for both the Vite and Bun plugins to ensure users can easily set up validation and typesafety.
+
+## Vite Plugin Improvements
+
+### 1. Introduction Page (`index.mdx`)
+- **Best Practice Pattern**: The "Quickstart" now shows the recommended pattern of exporting the schema as a named `Env` constant in `vite.config.ts`. This fixes the "anonymous schema" issue that broke type augmentation.
+- **2-Step Setup**: Added a clear "Step 2" section that shows the complete `src/vite-env.d.ts` snippet directly on the intro page.
+- **Simplified Installation**: Merged `arkenv` and `arktype` installation instructions into a single block.
+
+### 2. Typing Page (`typing-import-meta-env.mdx`)
+- **Missing Interface**: Added the `interface ImportMeta` block to the `vite-env.d.ts` snippet, which is required for some TypeScript configurations.
+- **Clarified Requirements**: Added a note about why `ImportMeta` is needed and clarified that `ViteTypeOptions.strictImportMetaEnv` is an optional feature requiring Vite 6.3+.
+
+### 3. Advanced Config Page (`arkenv-in-viteconfig.mdx`)
+- **Preamble**: Added a clear note at the top of the page explaining that this is an **advanced setup** for config variables (like `PORT`), distinguishing it from the standard application usage.
+
+### 4. Sidebar Reorder (`meta.json`)
+- Moved "Typing import.meta.env" before "Using ArkEnv in Vite config" to follow the natural setup flow.
+
+---
+
+## Bun Plugin Improvements
+
+### 1. Introduction Page (`index.mdx`)
+- **Typed by Default**: Updated the intro to emphasize that a complete setup includes typesafe `process.env`.
+- **Callout**: Added a prominent link to the typing guide as part of the "Simple setup".
+- **Heading Clarity**: Renamed "Advanced setup" to "Custom schema location" to better describe the use case.
+
+### 2. Typing Page (`typing-process-env.mdx`)
+- **Setup Completion**: Added a note clarifying that this guide is the final step of the standard setup.
+
+---
+
+## Verification Results
+
+- ✅ **Vite Setup**: Verified that `export const Env` in `vite.config.ts` combined with the new `vite-env.d.ts` snippet correctly types `import.meta.env.VITE_MY_VAR` in a test app.
+- ✅ **Documentation Flow**: The sidebar order now follows the user's setup journey (Intro -> Typing -> Advanced).
+- ✅ **Completeness**: All code snippets now include the necessary exports and interface augmentations to prevent "silent failures" in type checking.
diff --git a/openspec/specs/vite-config-usage/spec.md b/openspec/specs/vite-config-usage/spec.md
index 24c35c821..0a599a669 100644
--- a/openspec/specs/vite-config-usage/spec.md
+++ b/openspec/specs/vite-config-usage/spec.md
@@ -40,7 +40,7 @@ The schema SHALL be defined using ArkType's `type()` function (not as a raw obje
- **AND** they define the schema using `type()` outside of `defineConfig`
- **THEN** the schema can be defined once and used in both places
- **AND** TypeScript types are available in both contexts
-- **AND** the solution avoids code duplication and maintains type safety
+- **AND** the solution avoids code duplication and maintains typesafety
- **AND** `createEnv()` and the Vite plugin accept the type definition directly
### Requirement: loadEnv Wrapper Utility
@@ -55,7 +55,7 @@ The project SHALL support using ArkEnv with Vite's `loadEnv` function. Since `cr
- **AND** the same type definition can be passed to the Vite plugin for validating `VITE_*` variables
- **AND** no separate wrapper utility is needed
-### Requirement: Type Safety Constraint
+### Requirement: Typesafety Constraint
The environment object returned from `loadEnv` or any wrapper SHALL be typesafe. Unsafe patterns that bypass validation or type checking are FORBIDDEN.
@@ -71,7 +71,7 @@ The environment object returned from `loadEnv` or any wrapper SHALL be typesafe.
- **OR** a user attempts to use `as const` assertion on an environment object
- **THEN** the pattern is documented as forbidden
- **AND** examples demonstrate only typesafe patterns
-- **AND** documentation clearly explains why unsafe patterns (including `as const`) are not allowed and do not provide type safety
+- **AND** documentation clearly explains why unsafe patterns (including `as const`) are not allowed and do not provide typesafety
### Requirement: Documentation for Vite Config Usage
@@ -89,5 +89,5 @@ The project SHALL provide clear documentation and examples for using ArkEnv in v
- **THEN** they see an example of using ArkEnv with `loadEnv` in vite.config.ts
- **AND** the example demonstrates validating unprefixed variables for config use
- **AND** the example is clear and follows best practices
-- **AND** the example demonstrates both validation and type safety
+- **AND** the example demonstrates both validation and typesafety
diff --git a/packages/arkenv/CHANGELOG.md b/packages/arkenv/CHANGELOG.md
index 86f0cda96..a6441f603 100644
--- a/packages/arkenv/CHANGELOG.md
+++ b/packages/arkenv/CHANGELOG.md
@@ -426,7 +426,7 @@
- #### Support array defaults using type().default() syntax _[`#199`](https://github.com/yamcodes/arkenv/pull/199) [`e50dba1`](https://github.com/yamcodes/arkenv/commit/e50dba1f19418f8fc007dc786df1172067e3d07c) [@copilot-swe-agent](https://github.com/apps/copilot-swe-agent)_
- Fix to an issue where `type("array[]").default(() => [...])` syntax was not accepted by `createEnv` due to overly restrictive type constraints. The function now accepts any string-keyed record while still maintaining type safety through ArkType's validation system.
+ Fix to an issue where `type("array[]").default(() => [...])` syntax was not accepted by `createEnv` due to overly restrictive type constraints. The function now accepts any string-keyed record while still maintaining typesafety through ArkType's validation system.
##### New Features
diff --git a/packages/arkenv/src/standard-mode.test.ts b/packages/arkenv/src/standard-mode.test.ts
index 319de42ef..c0fedd986 100644
--- a/packages/arkenv/src/standard-mode.test.ts
+++ b/packages/arkenv/src/standard-mode.test.ts
@@ -82,7 +82,7 @@ describe("Standard Mode Type Inference", () => {
).toThrow(/Invalid validator: expected a Standard Schema 1.0 validator/);
});
- it("should maintain type safety with multiple validators", () => {
+ it("should maintain typesafety with multiple validators", () => {
vi.stubEnv("VAR1", "a");
vi.stubEnv("VAR2", "b");
vi.stubEnv("VAR3", "c");
diff --git a/packages/vite-plugin/CHANGELOG.md b/packages/vite-plugin/CHANGELOG.md
index c643a8f88..2c16b72f1 100644
--- a/packages/vite-plugin/CHANGELOG.md
+++ b/packages/vite-plugin/CHANGELOG.md
@@ -298,7 +298,7 @@
- #### `ImportMetaEnvAugmented` type helper for typesafe `import.meta.env` _[`#415`](https://github.com/yamcodes/arkenv/pull/415) [`79bef3c`](https://github.com/yamcodes/arkenv/commit/79bef3c26b87baf6bb3fe92da8bdfdb048a49e71) [@yamcodes](https://github.com/yamcodes)_
- Add a new `ImportMetaEnvAugmented` type that augments `import.meta.env` with your environment variable schema. This provides full type safety and autocomplete for all your `VITE_*` environment variables in client code.
+ Add a new `ImportMetaEnvAugmented` type that augments `import.meta.env` with your environment variable schema. This provides full typesafety and autocomplete for all your `VITE_*` environment variables in client code.
Implementation inspired by [Julien-R44](https://github.com/Julien-R44)'s [vite-plugin-validate-env](https://github.com/Julien-R44/vite-plugin-validate-env#typing-importmetaenv).
@@ -386,7 +386,7 @@
- #### Support array defaults using `type().default()` syntax _[`#224`](https://github.com/yamcodes/arkenv/pull/224) [`ecf9b64`](https://github.com/yamcodes/arkenv/commit/ecf9b64a680d3af5c5786b288fda35608590f7a9) [@yamcodes](https://github.com/yamcodes)_
- Fix to an issue where `type("array[]").default(() => [...])` syntax was not accepted by the plugin due to overly restrictive type constraints. The plugin now accepts any string-keyed record while still maintaining type safety through ArkType's validation system.
+ Fix to an issue where `type("array[]").default(() => [...])` syntax was not accepted by the plugin due to overly restrictive type constraints. The plugin now accepts any string-keyed record while still maintaining typesafety through ArkType's validation system.
##### New Features