Skip to content

Fix production signup API URL and harden CORS origin config#25

Merged
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/fix-production-signup-api-url
May 17, 2026
Merged

Fix production signup API URL and harden CORS origin config#25
ChrisAdamsdevelopment merged 1 commit into
mainfrom
codex/fix-production-signup-api-url

Conversation

@ChrisAdamsdevelopment
Copy link
Copy Markdown
Owner

@ChrisAdamsdevelopment ChrisAdamsdevelopment commented May 17, 2026

Motivation

  • The deployed frontend was sending signup requests to http://localhost:3001/api/register instead of the deployed backend, causing production signup to fail.
  • The intent is to make the frontend use a configured production backend URL while keeping a localhost fallback for local development.
  • The backend CORS list needed to be hardened so the deployed frontend origin is allowed and misconfiguration fails fast in production.

Description

  • Replaced the frontend hardcoded base URL with a Vite-controlled variable and a dev fallback by adding API_BASE_URL using import.meta.env.VITE_API_URL || (import.meta.env.DEV ? 'http://localhost:3001' : '') and throwing when missing in production, and updated all client fetches to use API_BASE_URL. (file: app.tsx)
  • Added temporary diagnostics around the register/signup request to log the register URL, HTTP status, response body on failure, and clear network/CORS error logs. (file: app.tsx)
  • Updated backend CORS handling to support ALLOWED_ORIGINS (comma-separated) and FRONTEND_URL, include common localhost origins in non-production, and fail fast in production if no allowed origin is configured; CORS now uses a function to validate incoming origins. (file: server.js)
  • Files changed: app.tsx and server.js (frontend base URL + request diagnostics, backend origin configuration).

Testing

  • Searched the codebase for occurrences of localhost:3001, 127.0.0.1, /api/register, register, Create Free Account, fetch(, and axios to locate the affected code paths; the client auth handler and multiple fetch calls were updated. (search ran successfully)
  • Ran the frontend build with npm run build; the build failed due to pre-existing TypeScript/dependency issues in this environment (missing react/type declarations and import.meta.env typing), not due to the URL/CORS changes.
  • Committed the changes and opened the PR; no automated unit tests were present or run as part of this patch.

Notes / Deployment instructions: set the following Render environment variables in your Render dashboard: for the frontend VITE_API_URL=https://YOUR_BACKEND_RENDER_SERVICE.onrender.com, and for the backend FRONTEND_URL=https://YOUR_FRONTEND_RENDER_SERVICE.onrender.com or ALLOWED_ORIGINS=https://YOUR_FRONTEND_RENDER_SERVICE.onrender.com,https://www.yourcustomdomain.com (keep localhost origins allowed for development).


Codex Task

Summary by Sourcery

Configure the frontend to use an environment-based API base URL and harden backend CORS origin handling to work correctly in production.

New Features:

  • Introduce an environment-driven API base URL with a localhost fallback for the frontend.

Bug Fixes:

  • Fix production signup and other API calls by redirecting them from a hardcoded localhost URL to the configured backend API base URL.

Enhancements:

  • Add logging and diagnostics around signup requests to surface URL, status, and error details for debugging.
  • Tighten backend CORS configuration to validate incoming origins against an explicit allowlist, including safer production defaults and local development origins.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 17, 2026

Reviewer's Guide

This pull request switches the frontend from a hardcoded localhost signup URL to a configurable API base URL with production-safe behavior and adds diagnostics around signup failures, while on the backend it replaces a single-origin CORS setting with a stricter, multi-origin configuration that fails fast when misconfigured in production.

Sequence diagram for signup request with API_BASE_URL and CORS validation

sequenceDiagram
  actor User
  participant FrontendApp
  participant BackendServer
  participant CorsMiddleware

  User->>FrontendApp: Submit signup form
  FrontendApp->>FrontendApp: Compute API_BASE_URL from VITE_API_URL or localhost
  FrontendApp->>BackendServer: fetch(API_BASE_URL + "/api/register")

  BackendServer->>CorsMiddleware: origin(origin, callback)
  alt origin allowed
    CorsMiddleware-->>BackendServer: callback(null, true)
    BackendServer-->>FrontendApp: Response (status, body)
    FrontendApp->>FrontendApp: Log status, error body on failure
  else origin blocked
    CorsMiddleware-->>BackendServer: callback(Error("CORS blocked for origin"))
    BackendServer-->>FrontendApp: Network/CORS error
    FrontendApp->>FrontendApp: console.error("Register request network/CORS error")
  end
Loading

File-Level Changes

Change Details Files
Make frontend API base URL configurable via Vite env with safe production behavior and update all fetch calls to use it.
  • Introduce API_BASE_URL constant derived from import.meta.env.VITE_API_URL with a localhost fallback only in dev mode.
  • Throw an error at startup if API_BASE_URL is missing in a production build to catch misconfiguration early.
  • Replace all usages of BACKEND_URL in auth, account, checkout, processing, and SEO fetch flows with API_BASE_URL.
app.tsx
Add targeted diagnostics for signup/register requests to help debug production issues.
  • Log the computed register API URL when in signup mode.
  • Log HTTP status codes for auth requests and response bodies when signup fails.
  • Log network/CORS errors specifically for signup failures before surfacing a generic error message to the user.
app.tsx
Harden backend CORS configuration to support multiple allowed origins, include localhost in non-prod, and fail fast on missing production configuration.
  • Parse FRONTEND_URL and ALLOWED_ORIGINS (comma-separated) into a normalized configuredOrigins list.
  • Define a set of LOCAL_DEV_ORIGINS and include them in allowed origins only when not in production.
  • Construct an allowedOrigins Set used by a dynamic CORS origin callback that allows requests with no origin, accepts only configured origins, and rejects others with a descriptive error.
  • Exit the process on startup in production if no allowed origins are configured, ensuring misconfiguration is caught immediately.
server.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ChrisAdamsdevelopment ChrisAdamsdevelopment merged commit b0ed581 into main May 17, 2026
4 of 5 checks passed
Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • The additional console logging around signup/login is useful for diagnostics but may be noisy in production; consider gating these logs behind an environment flag or removing them once the issue is resolved.
  • In the AuthScreen handler, you already compute requestUrl; using that variable in the signup debug log instead of re-constructing the URL would keep the logging consistent and reduce the chance of the log diverging from the actual request target.
  • The CORS origin callback currently throws an error for disallowed origins, which will surface as a generic server error; if you want clearer behavior for clients, consider returning a controlled 403-style response or a specific error body for blocked origins.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The additional console logging around signup/login is useful for diagnostics but may be noisy in production; consider gating these logs behind an environment flag or removing them once the issue is resolved.
- In the AuthScreen handler, you already compute `requestUrl`; using that variable in the signup debug log instead of re-constructing the URL would keep the logging consistent and reduce the chance of the log diverging from the actual request target.
- The CORS origin callback currently throws an error for disallowed origins, which will surface as a generic server error; if you want clearer behavior for clients, consider returning a controlled 403-style response or a specific error body for blocked origins.

## Individual Comments

### Comment 1
<location path="server.js" line_range="152-156" />
<code_context>
+  process.exit(1);
+}
+
 app.use(cors({
-  origin: ALLOWED_ORIGIN,
+  origin(origin, callback) {
+    if (!origin) return callback(null, true);
+    if (allowedOrigins.has(origin)) return callback(null, true);
+    return callback(new Error(`CORS blocked for origin: ${origin}`));
+  },
   methods: ['GET', 'POST'],
</code_context>
<issue_to_address>
**issue (bug_risk):** Returning an Error from the CORS origin callback will surface as a generic 500 instead of a clean CORS rejection.

Using `callback(new Error(...))` here makes CORS failures look like internal server errors (500) rather than a normal CORS rejection. Instead, return `callback(null, false)` for disallowed origins so the middleware cleanly denies the request. If you want observability, log the blocked origin separately but keep the callback as `callback(null, false)` to avoid misleading 500s for clients.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread server.js
Comment on lines 152 to +156
app.use(cors({
origin: ALLOWED_ORIGIN,
origin(origin, callback) {
if (!origin) return callback(null, true);
if (allowedOrigins.has(origin)) return callback(null, true);
return callback(new Error(`CORS blocked for origin: ${origin}`));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Returning an Error from the CORS origin callback will surface as a generic 500 instead of a clean CORS rejection.

Using callback(new Error(...)) here makes CORS failures look like internal server errors (500) rather than a normal CORS rejection. Instead, return callback(null, false) for disallowed origins so the middleware cleanly denies the request. If you want observability, log the blocked origin separately but keep the callback as callback(null, false) to avoid misleading 500s for clients.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c27c388486

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server.js
Comment on lines +22 to +25
const ALLOWED_ORIGINS = (process.env.ALLOWED_ORIGINS || '')
.split(',')
.map(origin => origin.trim())
.filter(Boolean);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep legacy ALLOWED_ORIGIN as CORS fallback

This change only reads ALLOWED_ORIGINS/FRONTEND_URL, so environments that were valid in the previous release with only ALLOWED_ORIGIN configured now produce an empty allowedOrigins set and immediately hit the production process.exit(1) path during startup. That creates a deploy-time outage for existing installations unless they also happened to set the new variables, so the old variable should be supported as a compatibility fallback (or migrated explicitly before enforcing the new keys).

Useful? React with 👍 / 👎.

Comment thread server.js
// ─────────────────────────────────────────────────────────────────────────────
const IS_PROD = process.env.NODE_ENV === 'production';
const FRONTEND_URL = process.env.FRONTEND_URL || 'http://localhost:5173';
const FRONTEND_URL = process.env.FRONTEND_URL || '';
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Validate FRONTEND_URL before checkout URL construction

By changing FRONTEND_URL to default to an empty string, the server can now start in production when only ALLOWED_ORIGINS is set, but checkout still builds Stripe success_url/cancel_url from FRONTEND_URL; in that configuration those URLs become relative (e.g. ?checkout=success...) and Stripe session creation fails, breaking paid upgrades. Add a production guard that requires a non-empty absolute FRONTEND_URL whenever checkout is enabled, or derive the redirect base from a validated configured origin.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant