LaunchWithCursor
Knowledgebase10 min read

Environment variables

.env vs .env.example, what to commit, managed platform keys, and using Deploy → Env vars without losing secrets.

Your app needs settings — API keys, database addresses, public URLs — that change between your laptop and production. Environment variables (often shortened to env vars) are how modern apps read those settings without hard-coding secrets into source files.

This guide is for founders who are new to the idea. You do not need to become a DevOps engineer; you need to know where values live and what LaunchWithCursor handles for you.

What is an environment variable?

An environment variable is a named value your app looks up at runtime, for example:

DATABASE_URL=postgres://...
JWT_SECRET=long-random-string
NEXT_PUBLIC_APP_URL=https://app.example.com

Your code (or framework) reads process.env.DATABASE_URL instead of embedding the password in a file that gets committed to GitHub.

Why this matters: Secrets in Git history are very hard to remove. Env vars keep passwords and API keys out of the codebase your collaborators and deploy system clone.

.env.example vs .env

Most LaunchWithCursor projects use two related files at the repo root (or app root in a monorepo):

FileCommitted to GitHub?What goes inside
.env.exampleYesEvery variable name your app expects, usually with empty or placeholder values. Documents the checklist for you and your AI assistant.
.envNo (never commit)Your real values for local development — Stripe test keys, JWT secrets, localhost URLs, etc.

Think of .env.example as the table of contents and .env as your private notebook.

Why commit .env.example but not .env?

  • .env.example helps anyone (including future you) know which keys must be set — without exposing actual passwords.
  • .env often contains production-like secrets even on a laptop. If it were pushed to GitHub, those secrets could be scraped within minutes.

Your .gitignore should list .env. Your AI assistant can add that line if it is missing.

Keep real values on your machine

Store working secrets in .env on your computer so you do not lose them between sessions. That file stays private on your laptop.

When you deploy:

  1. Open your local .env in your editor (or ask your AI assistant to list the keys — not the values — if you prefer).
  2. Go to Deploy → Env vars on LaunchWithCursor for your project.
  3. Use Copy name next to each suggested key from .env.example, paste the matching value from your local .env, and click Add.

You are copying your own values from a file you already trust — not inventing them from scratch on the website.

Why this matters: Founders often forget a Stripe or SendGrid key after weeks away from a project. Local .env is your backup; the dashboard is where production gets the same keys safely encrypted.

The Env vars page on LaunchWithCursor

On Deploy → Env vars you will see:

  • Suggested from .env.example — keys detected in your GitHub repo (the card stays visible while loading, on errors, and when there is nothing left to add). Copy each name, then enter the value in the add form below.
  • Current variables — what is stored for the next deploy. Values start masked; use the eye icon on a row to reveal a value, and the copy icon to copy it, so you can confirm a key holds the right value without retyping it. Revealing or copying a stored value is recorded in the audit log.
  • Saved For Later — a variable you keep but are not using yet. It shows with a purple bookmark, and the value is not sent to your app on deploy. Turn the toggle off when your app is ready for it.
  • Search — helpful once you have many keys.

After you change env vars, re-deploy the affected services so running containers pick up new values. Build-time keys (names starting with NEXT_PUBLIC_, VITE_, or REACT_APP_) require re-deploying front-end services after changes.

Need GitHub connected first? See Git & GitHub.

Platform-managed vs your own services

LaunchWithCursor injects some variables automatically when you turn on add-ons. They appear on the Env vars tab marked managed and cannot be edited.

You do not have to use platform Database, Redis, Storage, Email, or LaunchPay. If you already have Neon, your own R2 bucket, Resend, Stripe, etc.:

  1. Leave the matching flag in launchwithcursor.deploy.json as false (needsDatabase, needsRedis, needsStorage, needsEmail, needsLaunchPay).
  2. On Deploy → Env vars, add the same names your app already uses (DATABASE_URL, R2_*, provider-specific keys, …). Those stay editable until you provision the platform add-on.
  3. If you later want the platform service: ask your coding assistant to set the flag to true, commit, Sync from repo, then provision. The dashboard will warn you if you click Provision while the manifest still says no.

Provisioning a platform add-on replaces any value you had under that canonical name.

Variable(s)Added when you…Until then
DATABASE_URLProvision Postgres or MySQL on Deploy → DatabaseYou may set this yourself (e.g. Neon)
REDIS_URL, REDIS_KEY_PREFIXProvision Redis on Deploy → RedisYou may set these yourself (e.g. Upstash)
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME, R2_ENDPOINT, R2_PUBLIC_URLProvision R2 storage on Deploy → StorageYou may set these yourself
EMAIL_API_URL, EMAIL_API_KEY, EMAIL_FROM_DOMAIN, EMAIL_FROM_NAMESet up platform email on Deploy → EmailUse your own email provider keys instead
LAUNCHPAY_*Enable LaunchPayUse Stripe/Paystack/etc. keys as normal env vars
APP_ENVAlways managed for hosted appsDo not set
NODE_ENV=productionInjected on every deployDo not set

Redis Pub/Sub: provisioned Redis lets your app publish and subscribe on any channel — no extra permission is needed. Keys are already scoped to your app by REDIS_KEY_PREFIX, but pub/sub channel names are not, so use the prefix in channel names too (e.g. ck:my-app-a1b2:calls:room-1) to avoid messages crossing between hosted apps.

PORT is set automatically from each service’s internal port on Deploy → Overview. App listen-port vars like API_PORT / WEB_PORT are ignored on the platform — delete them if they show up in suggestions. This does not apply to third-party service ports such as SMTP_PORT, REDIS_PORT, or DATABASE_PORT — those are normal settings and are used as-is.

Why this matters: Copy-pasting a platform DATABASE_URL into Neon (or the reverse after you already provisioned) is the most common “works on my machine” failure. Pick one source per add-on.

What the LaunchWithCursor extension already does

When you install the extension and open your project, it copies a starter pack into .launchwithcursor/pack/LAUNCHWITHCURSOR/ with the canonical variable names and deploy rules your AI assistant should follow (SKILLS/Infrastructure.md, deploy checklists, etc.).

That means:

  • Your assistant should create or update .env.example with the right keys as features are built.
  • You should not need to memorize every infrastructure variable from this web page.
  • After provisioning add-ons on the dashboard, redeploy and let managed vars appear — your assistant reads them at runtime like any other env var.

Run LaunchWithCursor: Run Full Scan after changing .env.example so the dashboard suggestions stay in sync with your repo.

Quick checklist

  1. .env.example in Git — names only, placeholders OK.
  2. .env on your laptop — real values, never committed.
  3. Deploy → Env vars — copy names, paste values from local .env. Skip keys that already show as managed. Until you provision an add-on, you may set DATABASE_URL / R2_* / etc. yourself.
  4. Re-deploy after changes.
  5. Ask your AI assistant for anything confusing — that is what it is for.

Next steps