# 0.28.0 Hosts move to `server.domain`, `deploy.domain` and both `redirects` are removed, and `getEnv()` is renamed `env()`. A config that still has the old keys builds, but its domains are ignored: no certificates and no redirects on the next deploy. Make these changes before deploying. ## Domains Every host the app answers is now an entry in `server.domain`, with values from each environment's env file. Before: ```jsoc config.jsoc deploy: { domain: ["example.com", "www.example.com", "shop.example.com"], redirects: { "www.example.com": "example.com", }, env: { staging: { domain: "staging.example.com", }, }, } ``` After: ```jsoc config.jsoc server: { domain: { default: env!("DOMAIN"), "shop.example.com": env!("DOMAIN_SHOP"), }, }, ``` With one host, `server.domain` is a string: `domain: env!("DOMAIN")`. Add the values to every env file. `development.env` is committed, and its names end in `.localhost`, which every browser and curl send to your machine with no hosts file: ```text config/env/development.env DOMAIN=localhost DOMAIN_SHOP=shop.localhost ``` ```text config/env/production.env DOMAIN=example.com DOMAIN_SHOP=shop.example.com ``` ```text config/env/staging.env DOMAIN=staging.example.com DOMAIN_SHOP=shop.staging.example.com ``` A missing value fails the build, so a deploy with no `DOMAIN` in `production.env` fails before it goes live. Remove `domain` from `deploy` and from every `deploy.env.`. ## Routes Name Keys A route's `domain` is now a key of `server.domain`, and matches that key's host in the running environment. A route that named a host keeps working when the host is the key, as above. A second route for the development host goes: ```ts index.ts // before app.route({ domain: "shop.example.com", path: "/", handler: shop }); app.route({ domain: "shop.localhost", path: "/", handler: shop }); // after app.route({ domain: "shop.example.com", path: "/", handler: shop }); ``` Routes with no `domain` still answer every host. A `domain` that is not a key, such as `"*.example.com"`, still matches as a hostname. ## Redirects `deploy.redirects` and `deploy.env..redirects` are removed. The `www` pair of every `server.domain` value is a 301 to the value with no config: delete a `"www.example.com": "example.com"` entry, and do not list `www.example.com` as a domain unless it should serve the app itself. A value that starts with `www.` redirects the bare name to it instead. A redirect to another domain becomes a route: ```jsoc config.jsoc // before deploy: { redirects: { "old.example.com": "example.com" }, } // after server: { domain: { default: env!("DOMAIN"), "old.example.com": env!("DOMAIN_OLD"), }, }, ``` ```ts index.ts app.route({ domain: "old.example.com", path: "/*", handler: (req, res) => { res.redirect(`https://example.com${req.url}`, 301); }, }); ``` Register it before the domainless routes. ## Service Domains `deploy.services[].domains` keeps plain hosts, not keys. Read them from the env files so each environment has its own: ```jsoc config.jsoc services: [ { name: "api", port: 8080, domains: [env!("DOMAIN_API")] }, ], ``` ## getEnv Is env ```ts app/shared/stripe.ts // before import { getEnv } from "@elements/app"; if (getEnv() === "production") { ... } // after import { env } from "@elements/app"; if (env() === "production") { ... } ```