If you have an existing Next.js app, you’re probably already familiar with how environment variables work in Next. Check their docs here if you need a refresher.
Now forget all of that, and let’s simplify things with DMNO. 🥳
Initialize your Next.js integration
Using dmno init
we will automatically detect that you are using Next.js and install the necessary packages and configuration for you.
npx dmno init
pnpm dlx dmno init
yarn dlx dmno init
bunx dmno init
Skip to Configure… once this is complete.
Manual Setup
If you prefer, you can install dmno
itself and the @dmno/nextjs-integration
package manually:
npm add @dmno/nextjs-integration dmno
pnpm add @dmno/nextjs-integration dmno
yarn add @dmno/nextjs-integration dmno
bun add @dmno/nextjs-integration dmno
Then, in your next.config.mjs
file, import and initialize our dmnoNextConfigPlugin
:
import { dmnoNextConfigPlugin } from '@dmno/nextjs-integration';
/** @type {import('next').NextConfig} */const nextConfig = { // your existing config...};
export default nextConfig;export default dmnoNextConfigPlugin()(nextConfig);
Configure your environment variables
dmno init
will scaffold out the schema
in your config.mts
files based on your existing .env
files. See our Schema Guide for the specifics of how to author additional updates to your DMNO schema
.
Adjusting package.json scripts
Unlike some of our other integrations, this integration requires that you run your next
commands via dmno run
. The dmno init
setup helper will try to do this for you, but you’ll want to make sure your package.json scripts look something like this:
{ "name": "yourapp", "scripts": { "dev": "dmno run -w -- next dev", "build": "dmno run -- next build", "start": "dmno run -- next start", "lint": "dmno run -- next lint" }, // ...}
Accessing config
Use
DMNO_CONFIG
andDMNO_PUBLIC_CONFIG
instead ofprocess.env
🎉
You’ll now have fully typed and validated config, fine grained control over static/dynamic behaviour, and some cool security features described below.
Security, secrets, and leak detection
Only DMNO_PUBLIC_CONFIG
is available in code running on the client. That said, since Next.js does so much magic under the hood, it can be difficult to reason about whether the code you are writing will run on the server, client, or both. This makes it difficult to be 100% certain that your sensitive config will not be leaked.
To protect you from this risk, DMNO does has several security related features:
- Leak detection - built client-side code and server-rendered responses are scanned for any sensitive config items
- Log redaction - sensitive config values are redacted from
console.log
output and other console methods - HTTP request interception - http requests are intercepted and stopped if sending sensitive config to the disallowed domains
These features are opt-in - check out the security guide for more details.
Dynamic public config
If you’d like to be able to alter certain configuration values at boot time and load them in the client rather than relying on values bundled into your code, you need to expose an API endpoint which exposes this public+dynamic config.
See the dynamic config guide for more details.
Unfortunately, NextJS does not let us automatically inject the API route required to expose these config values, so if you want to use this feature, you must manually add an api route. This will be slightly different depending on if you are using app or pages router. Note the file paths in the examples below, they must match exactly.
export const dynamic = 'force-dynamic';export async function GET() { return Response.json((globalThis as any)._DMNO_PUBLIC_DYNAMIC_OBJ);}
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler( req: NextApiRequest, res: NextApiResponse) { res.status(200).json((globalThis as any)._DMNO_PUBLIC_DYNAMIC_OBJ)}
NOTE - fetching this config makes a blocking http request, so you should think carefully about if and how you use this feature, especially if performance is important your site. See the dynamic config guide for more details.