npm.io
1.2.1 • Published 6d ago

@ctroenv/nextjs

Licence
MIT
Version
1.2.1
Deps
1
Size
23 kB
Vulns
0
Weekly
586

@ctroenv/nextjs

npm version npm downloads license

Next.js adapter for CtroEnv — client/server env splitting with build-time validation and runtime access control.

Installation

npm install @ctroenv/nextjs

Usage

import { defineEnv, string } from "@ctroenv/nextjs"
import type { ClientServerSchema } from "@ctroenv/core"

const schema = {
  server: {
    DATABASE_URL: string().url(),
    JWT_SECRET: string().secret(),
  },
  client: {
    NEXT_PUBLIC_API_URL: string().url(),
  },
} satisfies ClientServerSchema

const env = defineEnv(schema)

// Server-side: all variables accessible
env.DATABASE_URL  // string
env.JWT_SECRET    // "********" (masked)
env.NEXT_PUBLIC_API_URL // string

// Client-side: server-only access throws
// env.DATABASE_URL → "Server-only environment variable..." error
Build-Time Validation
// next.config.ts
import { withCtroEnv } from "@ctroenv/nextjs"
import type { NextConfig } from "next"

const schema = { server: { ... }, client: { ... } }

const nextConfig: NextConfig = { /* your config */ }

export default withCtroEnv(schema, nextConfig)

Validates all environment variables at build start and logs errors before Next.js compiles.

API

Function Description
defineEnv(schema, opts?) Returns proxied env object with server/client access control
withCtroEnv(schema, config?) Next.js config wrapper with build-time validation
defineEnv
defineEnv<T extends ClientServerSchema>(
  schema: T,
  opts?: { maskWith?: string },
): InferredClientServerEnv<T>
Option Type Default Description
maskWith string "********" Custom string for masking .secret() values
Proxy Behavior

The returned env object uses a Proxy to enforce access control at runtime:

  • Server side: All keys from both server and client schemas are accessible.
  • Client side: Only client keys are accessible. Accessing a server key throws an error with a message suggesting NEXT_PUBLIC_ prefix.
  • Secret values: Keys marked with .secret() are masked to "********" (or custom maskWith). Raw values are accessible via env.meta.get("KEY").
  • meta object: Non-enumerable property providing .get(), .has(), .keys(), and .toJSON().
Secret Values
env.JWT_SECRET            // "********"
env.meta.get("JWT_SECRET") // actual value
env.meta.keys()           // ["DATABASE_URL", "JWT_SECRET", ...]
env.meta.has("JWT_SECRET") // true
env.meta.toJSON()         // { DATABASE_URL: "...", JWT_SECRET: "...", ... }

Types

import type { ClientServerSchema, InferredClientServerEnv } from "@ctroenv/core"
import type { InferredNextEnv } from "@ctroenv/nextjs"

// InferredNextEnv<T> is an alias for InferredClientServerEnv<T>

// Legacy type (deprecated — use ClientServerSchema instead):
import type { NextSchemaDefinition } from "@ctroenv/nextjs"

Documentation

Full documentation at ctroenv.vercel.app

License

MIT

Keywords