Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ dist
*.tsbuildinfo
.DS_Store
.wrangler
.env
.claude
plan.md
TODOs.md
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pnpm void deploy
- **One CLI** — deploy and manage your app on your Cloudflare account or your team's Void platform
- **Team platforms** — install a shared deployment service in your company's Cloudflare account and connect developers through the same CLI
- **Automatic provisioning** — use `void/db`, `void/kv`, `void/storage`, or `void/ai`, and Void provisions the resources your app needs
- **Typed secrets** — mark env schema keys with `.secret()`; direct Cloudflare deploys upload them as encrypted Worker secrets instead of plaintext vars
- **Typed production secrets** — schema-declared server keys are required in remote secret storage and rejected as plaintext Worker vars
- **File-based routing** — drop a file in `routes/`, get an endpoint with method exports, dynamic params, middleware, and [Standard Schema](https://standardschema.dev/) validation
- **Full-stack pages** — `pages/` directory for server-rendered UI with co-located data loading, SPA navigation, and typed forms (React, Vue, Svelte, Solid)
- **End-to-end type safety** — SQL migrations generate DB types, route handlers infer return types, typed fetch client checks everything at the call site
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ export default extendConfig(
{ text: 'Key-Value Storage', link: '/guide/kv' },
{ text: 'Object Storage', link: '/guide/storage' },
{ text: 'Environment Variables', link: '/guide/env-vars' },
{ text: 'Environment Migration', link: '/guide/env-migration' },
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ For production, add your API key as a project secret:
void secret put OPENAI_API_KEY=sk-...
```

For local development, add it to `.env.local` in your project root:
For local development, add it to `.env` in your project root:

```
OPENAI_API_KEY=sk-...
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/database/mysql.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Add a direct connection for local development:
DATABASE_URL=mysql://user:password@host:3306/app
```

Void reads `.env.local` for `void dev` and `void db` commands. In production, the Worker connects through the inferred `HYPERDRIVE` binding.
Void reads `.env` for `void dev` and `void db` commands. In production, the Worker connects through the inferred `HYPERDRIVE` binding.

## Define a schema

Expand Down Expand Up @@ -57,4 +57,4 @@ MySQL may implicitly commit schema changes. If a multi-statement migration fails

## Database commands

`void db push`, `generate`, `migrate`, `status`, `reset`, `seed`, `execute`, `studio`, `export`, `rename-migrations`, and `set-url` all understand MySQL. Local commands use `DATABASE_URL` from `.env.local`; `--remote` execution and Studio use the encrypted URL stored for a linked Void project.
`void db push`, `generate`, `migrate`, `status`, `reset`, `seed`, `execute`, `studio`, `export`, `rename-migrations`, and `set-url` all understand MySQL. Local commands use `DATABASE_URL` from `.env`; `--remote` execution and Studio use the encrypted URL stored for a linked Void project.
2 changes: 1 addition & 1 deletion docs/guide/database/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Add to your `void.json`:

### 2. Add your connection string

For local development, add `DATABASE_URL` to `.env.local`:
For local development, add `DATABASE_URL` to `.env`:

```
DATABASE_URL=postgresql://user:password@host:5432/mydb?sslmode=require
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ Select Cloudflare during setup, or run:
void deploy --platform cloudflare
```

Void supports full Worker apps, static sites, SPAs, and Cloudflare builds from supported frameworks. It provisions resources, applies migrations, and manages secrets for you. Commands such as `void secret put`, `void project logs`, and `void project rollback` then use the same account and Worker.
Void supports full Worker apps, static sites, SPAs, and Cloudflare builds from supported frameworks. It provisions resources, applies migrations, and manages secrets for you. `.env` stays local; production server keys declared in `env.ts` must exist in encrypted remote secret storage and are rejected as plaintext Worker vars. Commands such as `void secret put`, `void project logs`, and `void project rollback` then use the same account and Worker.

See the [Cloudflare guide](../integrations/cloudflare.md#deploy-to-your-own-cloudflare-account) for supported features, CI setup, and deployment limits.

Expand Down
93 changes: 93 additions & 0 deletions docs/guide/env-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Environment migration

The environment model now uses `.env` for local development only and remote secrets for every server-side production value. There are no compatibility shims for the previous four-file behavior.

## 1. Consolidate local development values

Merge the values you still need locally into `.env`:

```text
.env.local
.env.development
.env.development.local
→ .env
```

Delete every `.env.*` file, `.env.example`, and `.dev.vars*` file. Void fails fast when it finds one, rather than silently applying a precedence order.

Ensure `.env` is ignored by Git:

```text
.env
```

## 2. Move production server values remotely

For managed Void projects, upload each non-client schema key:

```sh
void secret put DATABASE_URL
void secret put STRIPE_KEY
```

To migrate a production file in one pass before deleting it:

```sh
void secret sync .env.production
```

The sync command validates every entry against `env.ts`. It rejects undeclared names, invalid values, and client-prefixed names.

For direct Cloudflare deployments, select Cloudflare and use the same commands:

```sh
void connect --platform cloudflare
void secret put DATABASE_URL
void secret put STRIPE_KEY
```

Remove those keys from `vars` in `wrangler.jsonc`. Void now treats any schema-declared server key in Worker `vars` as an error.

## 3. Supply client values at build time

Move `VITE_*` production values to CI/build-shell variables, or make the value an explicit schema default:

```sh
VITE_API_ORIGIN=https://api.example.com void deploy
```

Client values are compiled into browser assets and are public.

## 4. Remove masking modifiers

Change:

```ts
export default defineEnv({
STRIPE_KEY: string().secret(),
VITE_API_ORIGIN: url().public(),
});
```

to:

```ts
export default defineEnv({
STRIPE_KEY: string(),
VITE_API_ORIGIN: url(),
});
```

Server storage is selected by the absence of the client prefix, not a modifier. Invalid input is redacted uniformly.

## 5. Replace removed commands

`void env example` was removed because `.env.example` created a second dotenv source. Treat `env.ts` as the checked-in list of names, types, defaults, and requiredness.

Then verify:

```sh
void env check
void env check --remote
void deploy
```
Loading