Web field Plate 64 Route §64
Plate 64

The edge

TLS, certificates, and compression, without a Caddy sidecar and without a nginx.conf nobody on the team can read.

@atlas/edge terminates TLS, issues and renews Let's Encrypt certificates thirty days before expiry, and reverse-proxies to your app. In development with no DOMAIN set it detects localhost and serves plain HTTP on :8080 — no certs, no sudo.

Use the staging directory for the first production boot. Let's Encrypt allows five failures per hostname per hour, and the fastest way to spend that budget is a typo in a DNS record. The browser will call staging certs untrusted; that is the point of them.

What you are carrying

@atlas/edge

TLS termination, ACME, proxying, compression.

@atlas/security

Headers and rate limits at the boundary.

Start it

atlas init -n myedge --template edge

What it looks like

edge.tsts
import { LETSENCRYPT_PROD, LETSENCRYPT_STAGING, defineEdge, proxy } from "@atlas/edge"

defineEdge({
  acme: process.env.ADMIN_EMAIL
    ? {
        email: process.env.ADMIN_EMAIL,
        storage: process.env.CERT_DIR ?? "/var/atlas/edge",
        // ACME_STAGING=1 on the first prod boot. Five failures an hour is
        // not many when a DNS record is wrong.
        directoryUrl: process.env.ACME_STAGING ? LETSENCRYPT_STAGING : LETSENCRYPT_PROD,
      }
    : undefined,
  sites: [{
    host: process.env.DOMAIN ?? "localhost",
    compress: ["gzip", "zstd"],
    routes: [{ handler: proxy("http://localhost:3000") }],
  }],
}).listen()

Read next

@wess/atlas/edge @wess/atlas/security
Type to search guides and package references.