Summary#
app.Config declares the per-environment settings your application uses — non-secret values that differ between
development and production, such as an invite base URL (http://localhost:8099 locally, https://app.example.com in
production) or a from-address. It is the non-secret twin of declaring secrets (app.Secrets): you declare a setting's name in
source and supply its per-environment values out of band, but — unlike a secret — a setting's value is public and is
readable everywhere through the Config.Name handle, in a function body and in a component alike.
app.Config = [
new Setting("InviteBaseUrl") { Default = "http://localhost:8099" },
new Setting("FromAddress") { Default = "noreply@localhost" },
];
// read it anywhere by handle — it resolves to the running environment's value:
string invite = Config.InviteBaseUrl + "/accept?token=" + token;Signature#
app.Config = [ // one entry per named setting
new Setting("Name") { Default = "…" }, // Default: the value used when no .env supplies one
new Setting("Name"), // no Default: the value is REQUIRED from a .env file
];
Config.Name // the setting's value for the running environment (a string)app.Config is a list — an app may declare as many named settings as it needs.
Description#
A setting has a name (a string literal, the Config.Name read key) and an optional Default. The name and the
Default are the only things that live in source. The actual per-environment values come from two checked-in files that
sit next to your app.osy:
.env.developmentand.env.production— plainKEY=VALUEfiles (#comments and blank lines ignored). A key names a setting; its value is that setting's value for that environment.
These .env files are compile inputs, not runtime reads: when you compile, both value sets are baked into the app,
so one compiled app carries its development and its production values and needs no per-environment recompile. For each
setting, the value in each environment is the .env override if present, otherwise the setting's Default.
At runtime the app selects the set matching the environment it is running in — a local dev server resolves the
development values, a production deployment resolves the production ones — so Config.InviteBaseUrl reads
http://localhost:8099 locally and https://app.example.com in production, from the same build.
Reading a setting. Config.Name is a plain string value. Use it in a function body (building an email link,
choosing a from-address) and in a component (a link, a label). Reading a setting that is not declared in app.Config is
a compile error — a typo never silently reads as empty.
Required vs. defaulted. A setting with a Default always has a value. A setting without a Default is
required: if either .env.development or .env.production does not supply it, the compile fails — you cannot ship a
build that is missing a value in an environment it targets. An .env key that matches no declared setting is likewise a
compile error, so a stale or mistyped key is caught rather than silently ignored.
Not for secrets. app.Config values are stored and served in the clear — they are meant to be public (a URL, an
address), and a component can read them. An API key, token, or password belongs in declaring secrets (app.Secrets), which keeps its
value out of source and never sends it to a browser. A config value that looks like a secret (a long random token, an
sk-… key) is flagged with a warning nudging you toward app.Secrets.
Examples#
Declare two settings with development defaults, and read one in a function that builds an invite link:
app.Config = [
new Setting("InviteBaseUrl") { Default = "http://localhost:8099" },
new Setting("FromAddress") { Default = "noreply@localhost" },
];
string InviteLink(string token) {
return Config.InviteBaseUrl + "/accept?token=" + token;
}To give production a different value, add a checked-in .env.production next to your app.osy:
InviteBaseUrl=https://app.example.com
FromAddress=hello@example.comNow Config.InviteBaseUrl reads http://localhost:8099 when the app runs locally and https://app.example.com when it
runs in production — from one compiled build, with no code change.
See also#
- declaring secrets (app.Secrets) — the SECRET twin: a value kept out of source and never served to the client
- embedding provider (app.Embedding) — another
app.Xconfig block (the embedding model) - default LLM model (app.DefaultModel) —
app.DefaultModel, the app's default LLM config