Getting Started
Let's be honest - most configuration tools make you write a novel before you can generate a single file. Not here. You can start with just a few lines and grow from there.
The Absolute Minimum
Create an axogen.config.ts
file:
import {defineConfig, env} from "@axonotes/axogen";
export default defineConfig({
targets: {
app: env({
path: "app/.env",
variables: {
NODE_ENV: "development",
PORT: 3000,
},
}),
},
});
Run it:
axogen generate
Boom. You've got an app/.env
file. Not earth-shattering, but you're up and
running.
Adding Environment Variables
Of course, hardcoded values aren't very useful. Let's make it read from your actual environment:
import {defineConfig, env, loadEnv} from "@axonotes/axogen";
import * as z from "zod";
const envVars = loadEnv(
z.object({
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string(),
})
);
export default defineConfig({
targets: {
app: env({
path: "app/.env",
variables: {
PORT: envVars.PORT,
DATABASE_URL: envVars.DATABASE_URL,
},
}),
},
});
Create a .env.axogen
file with your values:
PORT=3000
DATABASE_URL=postgresql://localhost:5432/myapp
Add .env.axogen
to your .gitignore
file! It's just like any other .env
file - you don't want to push your secrets to git.
Now when you run axogen generate
, it validates your environment variables and
generates the config. If DATABASE_URL
is missing, it'll yell at you. No more
silent failures.
Multiple Formats
Here's where it gets interesting. Need the same data in different formats? Easy:
import {defineConfig, env, json, loadEnv} from "@axonotes/axogen";
import * as z from "zod";
const envVars = loadEnv(
z.object({
PORT: z.coerce.number().default(3000),
DATABASE_URL: z.string(),
})
);
export default defineConfig({
targets: {
app: env({
path: "app/.env",
variables: {
PORT: envVars.PORT,
DATABASE_URL: envVars.DATABASE_URL,
},
}),
config: json({
path: "config.json",
variables: {
database: {
url: envVars.DATABASE_URL,
},
server: {
port: envVars.PORT,
},
},
}),
},
});
One source of truth, multiple outputs. Your backend reads the .env
, your
frontend build process reads the JSON. They're always in sync.
Adding Commands
Sometimes you want to run things after generating configs:
export default defineConfig({
targets: {
// ... your targets
},
commands: {
start: "npm start",
dev: "npm run dev",
},
});
axogen run start
CLI Reference
# Generate all targets
axogen generate
# Generate specific target
axogen generate --target app
# See what would be generated (without writing files)
axogen generate --dry-run
# Run commands
axogen run start
# Get help on any command
axogen run --help
axogen generate --help
What's Next?
This is the foundation. Start small, grow as needed. Check out:
- Basic Configuration - Core concepts and patterns
- Target Types - All the file formats you can generate
- Commands System - Task management and automation
Configuration management doesn't have to suck. Your environment variables can have types. Your scripts can be intelligent. Your deployments can be consistent.
That's the way.