There is fresh movement around I stopped maintaining 30 JSON files by hand with this one tool, and the story is worth a closer look.
We pulled together what is known so far and what it could mean for the people following it.
If you’ve ever wondered how to reuse configuration values or how to easily inject them into your code, then I have the perfect tool for you. It’s not just a JSON replacement but something more powerful that works with several config formats.
Jsonnet is a JSON superset (extension) that evaluates dynamic data. It’s a configuration language that links many JSON files together through shared values. You specify values and functions in common Jsonnet files, then use them to generate your JSON, TOML, and YAML configuration files.
Jsonnet looks nearly identical to JSON, without the mandatory quotations around keys. To quickly see what I mean, you can install Jsonnet using your distro’s package manager and execute:
Using “exec” causes Jsonnet to interpret the file path as code instead.
Let’s look at a more complicated example. Using the command jsonnet example.jsonnet, the following Jsonnet code…
You can see the use of the variable “replicas” too, but that’s not the only dynamic feature it offers. Jsonnet supports functions, inheritance, conditionals, imports, and even Python-like list comprehensions.
Inheritance is one of the more useful features—although some don’t like it in configuration languages, I think it’s necessary.

The “base + …” inherits (and merges) values from “base.” The “bar+” tells Jsonnet to merge that nested object too; without it, the child “bar” clobbers (overwrites) the parent.
Here’s a simple example of a function. Functions can return any valid data type, including other objects:
As mentioned, Jsonnet supports JSON, TOML, INI, and YAML. Many modern tools use such file formats and also typically require domain-specific knowledge (such as service names, URLs, etc.). Examples include Docker, Kubernetes, build orchestration tools (like Nx), task runners, and much more. Having a central registry to tie in project-specific configuration values is a massive help.
Runtime code often relies on environment variables, and since Jsonnet can produce raw strings, you can generate just about any file imaginable and plug in the necessary values. Sometimes I output .env files, other times raw constants/types in dedicated Python or Go files. Jsonnet has an extensive string manipulation library. While not perfect, I’ve rarely encountered an issue I could not resolve.
Glue code was something I had been trying to tackle for a while. I often create a monorepository for large projects, and associating types between packages and languages is a major sticking point. Docker services alone require multiple configuration files for production, development, testing, and even debugging. I probably have 20 to 30 configuration and code files that pull the project together. Without Jsonnet, I wouldn’t be able to cope.
These two formats are a lot more similar than their acronyms suggest.
Jsonnet is also super simple to learn. It looks like a blend of JSON and Python, which is familiar to most people. I hit the ground running, and there was no upfront cost of picking up yet another skill, as there is with similar tools such as KCL or CUE.
Google maintains Jsonnet too, and with widespread adoption, it’s not going away.
Like most configuration languages, it’s side-effect-free, meaning you can’t touch the disk, make network requests, or similar.

I use Jsonnet as a central registry. Within a “config” directory at my repository root sit all my Jsonnet configuration and library files. Inside my regular code packages, where my vanilla config files live, I create similarly named Jsonnet files:
I use a task runner (like Taskfile, Mise, or Nx) to find the Jsonnet files in “apps” and then generate collocated configuration files from them. Those files import “config” values and functions, which provide domain-specific data.
I’m still exploring how to configure a Jsonnet project, but it’s important to note that Jsonnet does not hoist functions or “local” variables, which affects configuration value layout. However, it supports lazy evaluation, which we can leverage for more flexibility.
Hoisting moves declarations to the top of their scope, so you can call a function (for example) before the line it’s defined on. It’s found in JavaScript, among other languages.
Values inside objects and “local” variable blocks (first line in the code above) perform lazy evaluation, which means they’re only processed at the moment they’re needed. Consequently, order doesn’t matter, so we can organize our values in almost any way.
Jsonnet is easy to pick up, it’s not going away, and it solves a real problem in larger projects: connecting disconnected components. Why wouldn’t I use it?
Is it perfect? No, but it’s good enough and flexible enough to shim and make it work in ways not initially intended.
Jsonnet was the missing piece in my projects, and the fact that it can generate glue code from configuration values is an enormous plus.
If you’re interested in Jsonnet, check out their homepage, documentation, and GitHub repository for more information.
I ditched VS Code for Zed instead of going for Google’s Antigravity, and now the editor feels genuinely fast