Skip to content
DMNO

.blog/

Level up your env var tooling in Next.js with DMNO

We’re super excited to finally announce that our Next.js integration is ready - and we believe it is the BEST way to manage configuration in Next.js apps. Dealing with config is Next.js has usually been an afterthought - use process.env, maybe a .env file, and call it a day. But the whole experience is clunky and leaves you open to some major security risks.

Here’s a quick overview of the main problems and how DMNO solves them:

👷 Beyond type-safety

Problem: Environment variables are always plain strings, so you must coerce and validate them yourself (if at all). You also won’t get any types on process.env unless you manually add them, and you probably shouldn’t put a coerced non-string values back into process.env anyway.

Solution: DMNO lets you define a simple schema for your config. Aside from being more clear, this lets us do some magical things:

  • Easily add coercion and validation to your config, so you are guaranteed the data is what you think it is
  • Validates your config during your build and before boot, so you’ll know exactly what’s wrong before bringing down prod
  • Auto-generated TypeScript types that match your schema, including detailed JSDoc comments explaining what each config item does

Validation demo

Intellisense demo

🔐 Effortless secure collaboration

Problem: Every time we onboard a new team member or add a new external service, we often need to share some set of secrets. You’ve never sent anything like that over slack… right?? Not to mention needing to keep all the various platforms we build, test, and run our applications on all in sync.

Solution: With your schema as part of your repo, you’ll never pull down the latest only to be met with unexpected crashes due to missing config. Inline documentation and validations let you know exactly what each config item does, and whether it is required. Plugins let you sync sensitive config securely, either encrypted in your repo, or with secure backends like 1Password. Plus unifying how config is managed makes it much easier to reason about and debug.

1Password demo

🤐 Leak detection

Problem: With the edges of client and server getting blurrier each day, it has become easier to accidentally leak sensitive config. Your secrets can end up in server-rendered pages and data, built javascript code, or be sent to the wrong 3rd party - especially logging and error tracking tools.

Solution: DMNO does everything possible to protect you from accidental leaks. These features are opt-in but we think they are invaluable.

  • DMNO patches global console methods to scrub sensitive data from logs
  • Built client JS files and outgoing server responses are scanned for leaks before they are sent over the wire
  • outgoing HTTP requests are scanned to make sure secrets can only be sent to whitelisted domains - e.g., only send your Stripe key to api.stripe.com

Log redaction demo

Astro leak middleware demo

HTTP interception demo

📐 Dynamic configuration control

Problem: The NEXT_PUBLIC_ prefix controls whether config is public AND whether it will be static, meaning replaced at build time. If you want build once and deploy for multiple contexts, you’ll have to awkwardly wire up fetching the config on your own.

Solution: DMNO decouples the concepts of “sensitive” and “dynamic”, and supports both sensitive+static and public+dynamic config, and lets you set them explicitly in your config schema. This finer control is easier to reason about and we handle the hard part for you. See our dynamic config guide for more details.

Dynamic schema example

🌲 Unified config system

Problem: In a larger projects, especially monorepos, each part of your system ends up with its own hacked together config tooling, and there’s no way to share config across services. Keeping things in sync is error-prone and awkward, and dealing with many different tools is a pain.

Solution: DMNO lets you easily define config once and share it across your entire monorepo. Even outside of monoepos, using the same config system across your entire project will make your life much easier.

Pick schema example

⛓️ Flexible value dependencies

Problem: Ideally we could set config values based on other values. While Next.js does have some built-in handling of multiple environment specific .env files (e.g., .env.production), this behavior is tied to the value of NODE_ENV. Since npm module installation behavior is also affected by this, often you’ll end up running your build with NODE_ENV as development even when doing a non-production build. You can also use $ expansion to do some basic referencing, but it’s extremely limited.

Solution: DMNO’s config resolution logic allows you to reference other values however you like. You can define switching logic based on any value (not just NODE_ENV) and reuse values within arbitrary functions. Your configuration schema all forms a reactive DAG, which can also be visualized for simple debugging.

Config reuse schema example


So what’s Next

While much of what was described above is not specific to Next.js, a TON of specific work went into making sure our Next.js integration just works without additional setup on your part. We want this to become the default way that everyone deals with configuration in their Next apps, and for JS/TS in general. This stuff may seem like it’s not a problem, and day to day it may not be - until it bites you. Setting up your schema isn’t much harder than writing a .env.example file and you get SO much more, so please give it a try, and let us know what you think!

Type-safe and secure Astro configuration with DMNO

ENV VARS Astro CTO Matthew Phillips presenting Astro’s new astro:env feature at Astro Together in Montreal.

Configuration in Astro has improved drastically in recent weeks. We launched DMNO, including our Astro integration, and shortly after Astro launched their official (experimental) astro:env feature in version 4.10. We were very excited to see this on the main stage at Astro Together in Montreal (see above ^^), and to talk with the core team about how we can work together to make configuration in Astro even better. There’s already some great cross-pollination happening, and we’re excited to see where it goes.

We’re really glad to see Astro taking configuration seriously, and we’re excited to see how the community uses these new tools to build even better sites. That said, we do think DMNO has some unique advantages that make it a great choice for many Astro projects, especially if you want to share config among other services, or collaborate securely with your teammates.

Here’s a quick overview of what DMNO can do for you:

Key Features

  • True type-safety Your config values are coerced, validated, and accessible with complete type-safety. Fail fast and early rather than bringing down production. Validation demo

  • Built-in docs for your config We generate very rich types from your config schema, giving you built-in docs (Intellisense) for all of your config. Intellisense demo

  • Store secrets securely: Use plugins to store and sync your sensitive config items in an encrypted file within your repo or remotely in 1Password. More secure backends coming soon! No more insecurely sharing secrets over slack! 1Password demo

  • Leak detection: DMNO ensures that only non-sensitive config is accessible on the client side, and ensures sensitive config is never leaked by injecting an Astro middleware that scans rendered server responses before sending them over the wire. Astro leak middleware demo

  • Log redaction: DMNO redacts sensitive data from all global console method output, ensuring that your secrets are never exposed or persisted in your logs. Log redaction demo

  • HTTP interception: DMNO intercepts HTTP requests to prevent sensitive data from being sent to the wrong third-party services. e.g., Only send your Stripe key to api.stripe.com. HTTP interception demo

  • Share config items in your monorepo: Unified config system for all of your services, with the ability to easy reuse items from the root or other services. Even outside of monorepos, using the same config system for your entire stack simplifies things.

  • Static and dynamic config: Fine control over which items are static (injected at build time) vs dynamic (loaded at boot), with additional safe-guards around using dynamic config during static pre-rendering. We even support dynamic public config loaded at runtime.

Plus it’s super easy to get started:

  • Automatic initialization: Using dmno init, DMNO detects your Astro setup, automatically installs necessary packages, and updates your Astro config file.

  • Easy scaffolding: DMNO scaffolds your config schema based on existing .env files and references to env vars throughout your codebase.

  • Accessible config objects: Just swap your calls from process.env/import.meta.env to the DMNO_CONFIG global that is automatically injected into your application. This gives you access to your type-safe config, helpful errors, and access to public+dynamic config items (if applicable).

Astro-specific features:

Most of these features are standard to DMNO, but there are a few Astro specific benefits and features:

  • Use env vars in astro config: Easily access env vars directly in your astro.config.* files.

  • Middleware injection: Automatically injects a middleware which detects leaked secrets in rendered responses as well as built js files being sent to the client. This middleware also warns if you accidentally use dynamic config items during pre-rendering of static pages.

  • Adapter support: Full support for the Netlify and Vercel adapters, with more in the works.

Get started

DMNO provides the most powerful way to manage configuration in Astro projects, all while enhancing security, and improving developer experience.

All it takes is npx dmno init 🎉

For more detailed information, visit the DMNO Astro Integration Guide.

Announcing DMNO's Developer Preview

Hello DMNO 👋

We (Theo and Phil), are happy to announce the Developer Preview of our new project, DMNO. Our first release is a configuration engine that helps you manage your configuration in a single place, and access it in a type-safe way across your services.

We’ve been heads down working on this project for a while now, and we’re excited to share it with you and let the community shape its future. While it’s still early days, we’re can’t wait to see what you build with it.

To make things easier to get started we’ve created a few integrations with popular frameworks and tools, and we’re working on more.

We’ve also created a few plugins to help you securely manage your secrets and other sensitive configuration items.

To get started you can check out our quickstart guide, or dive into our schema guide.

We’ve also create a short video that goes over the basics of DMNO, and how it can help you manage your configuration. Check it out below:

What’s next?

We will continue to build out more integrations, and evolve our configuration engine in response to your feedback.

In addition to that, we have two big products on the horizon:

  • DMNO Dev: A UI-driven way to run your full stack apps locally, powered by DMNO’s configuration engine.
  • DMNO Deploy: A way to deploy your apps to your existing platforms, powered by DMNO’s configuration engine.

Our goal is to make it as seamless as possible for you to configure, run, and deploy your entire stack and we’re just getting started!