# --------------------------------------------------------------------------- # SHARP-ER web (React Router 8) - environment template # # Copy to .env and fill in real values: cp .env.example .env # Never commit .env. # # `pnpm --filter web start` loads THIS file (apps/web/.env), the same way the # CMS loads apps/cms/.env. It is per-application on purpose: PORT and HOST mean # something different to each server, and a single shared value would move # Strapi onto the website's port. The repository-root .env is docker compose's # file and is not read here. # # A real environment variable always wins over this file, so a systemd unit, # a container or `PORT=9090 pnpm --filter web start` overrides any line below. # # `pnpm dev:web` does NOT read this file - the dev server is Vite on 5173, and # it only exposes variables prefixed VITE_, by inlining them into the CLIENT # bundle. Never use that prefix here: STRAPI_TOKEN below is a server secret. # --------------------------------------------------------------------------- # --- Server ---------------------------------------------------------------- # Port react-router-serve binds. Leave it unset and the server takes the first # FREE port from 3000 upwards - 3001, 3002, ... once 3000 is busy - which a # reverse proxy cannot be pointed at. `pnpm dev:web` ignores this and uses 5173. PORT=3000 # Interface to bind. Unset means every interface. Set it to 127.0.0.1 when a # reverse proxy on the same host should be the only way in. # HOST=127.0.0.1 # --- Content --------------------------------------------------------------- # Public origin of the site. Canonical URLs, hreflang alternates and JSON-LD # are built from it, so it must match how visitors actually reach the site - # https://sharper.ly in production, never the internal http://127.0.0.1:3000. # Leave it unset in local development and the request's own host is used. SITE_URL=http://localhost:3000 # Where the server-side loaders fetch content from. This origin is also # prefixed onto uploaded media URLs, which the browser has to resolve too - # see "Images from the CMS" in README.md. STRAPI_URL=http://localhost:1337 # Optional Strapi API token. Only needed to read draft or otherwise protected # content; published content is public. Settings -> API Tokens in the admin. STRAPI_TOKEN= # --- Bot protection -------------------------------------------------------- # Cloudflare Turnstile on the public forms (contact, event registration and # both application forms). Both keys or neither: with either one empty, no # widget renders and submissions are not checked. The site key is public and # reaches the browser; the secret key never does. # Cloudflare dashboard -> Turnstile -> your widget. For local testing, # Cloudflare's always-pass pair is 1x00000000000000000000AA (site) and # 1x0000000000000000000000000000000AA (secret). TURNSTILE_SITE_KEY= TURNSTILE_SECRET_KEY=