Title

Domain Search: fix prod failure (env, base URL, CORS, HTTPS)

What’s happening

Works in Replit UI → fails on live → likely:

client calls http://localhost:**** or preview URL instead of relative /api

missing API key env in the live runner

CORS not allowing the live origin

mixed content (http target from an https page)

Please do the following
1) Instrument & check the error

Open the browser Network tab on live and confirm the failing request and response status/body.

Also add temporary logging around the fetch to capture the full error:

File: client/src/services/domain-search.ts (or wherever the fetch lives)

--- a/client/src/services/domain-search.ts
+++ b/client/src/services/domain-search.ts
@@ -1,6 +1,13 @@
-const API_BASE = import.meta.env.VITE_API_BASE_URL || "http://localhost:5000";
+// Use relative path in prod to avoid mixed content and wrong host
+const API_BASE = import.meta.env.VITE_API_BASE_URL || "";
 
 export async function checkDomain(name: string) {
   try {
-    const res = await fetch(`${API_BASE}/api/domain/search?name=${encodeURIComponent(name)}`);
+    const url = `${API_BASE}/api/domain/search?name=${encodeURIComponent(name)}`;
+    console.debug("[domain] fetch →", url);
+    const res = await fetch(url, { credentials: "include" });
+    if (!res.ok) {
+      const txt = await res.text().catch(()=> "");
+      console.error("[domain] bad status", res.status, txt);
+    }
     return await res.json();
   } catch (e) {
     console.error("[domain] fetch error", e);
     throw e;
   }
}

2) Ensure server route + CORS allow the live origin

File: server/index.js (Express)

+const cors = require("cors");
+const allowed = (process.env.CORS_ORIGINS || "").split(",").filter(Boolean);
+app.use(cors({
+  origin: (origin, cb) => {
+    if (!origin) return cb(null, true);        // allow same-origin / curl
+    if (allowed.length === 0) return cb(null, true);
+    cb(null, allowed.includes(origin));
+  },
+  credentials: true,
+}));
+app.set("trust proxy", 1);


In Replit Secrets, set CORS_ORIGINS to your live URL, e.g.
https://<your-live>.replit.dev,https://<custom-domain-if-any>

3) Don’t hardcode localhost anywhere

Search the repo for these strings and replace with relative /api or VITE_API_BASE_URL:

http://localhost:
https://*.repl.co
https://*.replit.dev

4) Verify env vars exist in production runner

Ensure the registrar provider key(s) are present in Replit Secrets:

REGISTRAR_API_KEY (or GODADDY_API_KEY / NAMECHEAP_API_KEY etc.)

Any required secret must be available to the server process on live.

In the server route handler, log a redacted presence check once (on boot):

console.log("[domain] api key present:", !!process.env.REGISTRAR_API_KEY);

5) Enforce HTTPS to provider

If the server is calling an external registrar API, confirm the URL uses https and not http (mixed content will fail on your https page).

6) Example server route (robust error logs)

File: server/routes/domain.js (or inline)

app.get("/api/domain/search", async (req, res) => {
  const name = String(req.query.name || "").trim();
  if (!name) return res.status(400).json({ error: "Missing name" });
  try {
    // call provider here; example:
    const r = await fetch(`https://api.example.tld/domains/lookup?name=${encodeURIComponent(name)}`, {
      headers: { Authorization: `Bearer ${process.env.REGISTRAR_API_KEY}` }
    });
    const txt = await r.text();
    if (!r.ok) {
      console.error("[domain] provider error", r.status, txt);
      return res.status(502).json({ error: "Provider error", status: r.status });
    }
    res.type("application/json").send(txt);
  } catch (err) {
    console.error("[domain] server error", err);
    res.status(500).json({ error: "Lookup failed" });
  }
});

7) Acceptance (on live)

Network tab shows a 200 from GET /api/domain/search?name=...

No CORS errors

The red toast (“Search failed…”) never appears for valid names

If provider is down, UI shows a graceful message (keep the toast, but log server-side details)