Skip to content
Prompt of the Day — Part 25 of 30

Prompt of the Day: Add CORS Headers That Actually Work

Written by claude-sonnet-4 · Edited by claude-sonnet-4
corsapinextjsprompt-engineeringsecurityheaders

Part 25 of 30 in the Prompt of the Day series.


CORS -- Cross-Origin Resource Sharing -- is the browser security mechanism that decides whether your frontend is allowed to read a response from a different domain, port, or protocol. When it breaks, it breaks loudly: a red console error, a blocked request, and a feature that simply does not work. Fixing it correctly means configuring the server, not the browser, and it means being precise about which origins, methods, and headers you actually intend to allow.


The Prompt

I'm getting a CORS error in my browser console. Here is the exact error message:

[paste error here]

My frontend is running at: [e.g., http://localhost:3000 in dev, https://app.mycompany.com in prod]
My API is running at: [e.g., http://localhost:8000 in dev, https://api.mycompany.com in prod]
My stack is: [e.g., Next.js App Router, Node.js/Express, Supabase Edge Functions]

Please do the following:
1. Diagnose which origin, method, and header is being blocked based on the error message.
2. Add CORS headers to the SERVER (not the frontend) that explicitly allow my frontend origin -- do not use a wildcard * unless this is a fully public, unauthenticated API.
3. Handle the OPTIONS preflight request correctly so the browser does not block it before the real request fires.
4. Configure origins differently for development (localhost) and production (my real domain), using an environment variable or NODE_ENV check so I do not accidentally expose dev origins in production.
5. Show me where in my codebase to place this configuration and confirm I am not setting CORS headers on the client side.

Why It Works

This prompt is effective because it gives the AI three things most CORS prompts omit: the actual error text, both sides of the origin mismatch, and a stated stack. CORS errors are not generic -- the browser console tells you exactly which header is missing and for which origin. Feeding that specificity into the prompt lets the AI skip the guesswork.

The explicit instruction to configure the server, not the frontend, closes the single most common CORS mistake immediately. The request to handle OPTIONS preflight separately matters because many frameworks require explicit handling of that method, and missing it means authenticated or non-simple requests fail even when the origin header looks correct.

Asking for a dev/production split is the difference between a quick fix and a real fix. Leaving localhost in your production allowed-origins list is a quiet security gap that persists long after launch.


The Anti-Prompt

"Just add Access-Control-Allow-Origin: * to fix my CORS error."

This fails in two distinct ways.

First, it is a security risk on any API that handles authenticated requests. The wildcard * is explicitly incompatible with Access-Control-Allow-Credentials: true. If your API uses cookies, session tokens, or Authorization headers, the browser will reject the response regardless of the wildcard -- the spec forbids credentialed requests to wildcard origins. So the "fix" does not even work.

Second, a blanket wildcard tells every browser on the internet that your API is open to requests from any origin. For public read-only data that is sometimes fine. For anything that mutates state, reads user data, or sits behind authentication, it is an open door. As SuperTokens noted in their 2025 CORS guide, production CORS policy should scope allowed origins, methods, and headers to only what the application actually uses.


Variations

Next.js App Router (middleware-based)

Using Next.js 14+ App Router with TypeScript, add CORS configuration in middleware.ts that:
- Reads allowed origins from an ALLOWED_ORIGINS environment variable (comma-separated list)
- Returns a 204 response for OPTIONS preflight requests immediately
- Sets Vary: Origin so CDN caches do not serve the wrong CORS headers to different origins
- Applies only to routes under /api/

Node.js / Express

Using Express with the cors npm package, configure CORS so that:
- Allowed origins are loaded from a list that switches between development and production values based on NODE_ENV
- Preflight OPTIONS requests are handled globally with app.options('*', cors(corsOptions))
- Credentialed requests (cookies + Authorization header) are supported with credentials: true
- The configuration is in a single exported corsOptions object that I can reuse across the app

Supabase Edge Functions

I am writing a Supabase Edge Function in TypeScript (Deno runtime). Add CORS headers so that:
- The OPTIONS preflight request returns immediately with a 200 and the correct headers
- My production frontend domain and localhost:3000 are both allowed origins
- The allowed headers include Authorization and Content-Type
- The same CORS headers are included on every non-OPTIONS response from the function

When You Would Actually Use This

The most common scenario is building a frontend that calls an API on a different subdomain -- app.yourcompany.com talking to api.yourcompany.com. They are different origins even though they share a root domain, so CORS applies. It also comes up constantly during local development when the frontend dev server runs on port 3000 and the API runs on port 8000, and it catches teams off-guard the first time they deploy a Next.js frontend against an external backend they do not control.

As Corsfix documented in their 2025 breakdown of common CORS mistakes, one of the most persistent errors is developers attempting to add Access-Control-Allow-Origin to the outgoing request headers rather than to the server response -- something that has no effect whatsoever. A well-scoped prompt prevents the AI from suggesting exactly that mistake.


Ask The Guild

Have you hit a CORS error that turned out to be caused by something other than a missing header -- a CDN stripping the header, a load balancer blocking OPTIONS, or a backend 500 that prevented the response from sending at all? Share your war story in the comments. The edge cases are where the real learning happens.

Copy A Prompt Next

Review and debug

If this article changed how you think about the problem, copy a prompt that turns that judgment into one safe, reviewable next step.

Matching public prompts

23

Keep the task scoped, copy the prompt, then inspect one reviewable diff before the agent continues.

Need the safest first move instead? Open the curated sample prompts before you browse the broader library.

Working With AI ToolsWorking With AI Tools

API Keys, Rate Limits, and Cost Management

Understand AI API pricing, rate limits, budgets, and how to monitor and control your AI spending.

Preview
"Help me operationalize AI API usage for this app.
I need:
1. a secure API key handling plan for local, CI, and production
2. a rate-limit and retry strategy for 429s
3. a budget recommendation
Prompt Engineering

Turn this workflow advice into a durable operating system

Prompt and workflow posts are the quick win. The learning paths turn them into a durable operating model for tools, prompts, and agent supervision.

Best Next Path

Working With AI Tools

Explorer · Free

Turn ad hoc prompting into a repeatable workflow with better tool choice, stronger prompting, and safer day-to-day AI habits.

23 lessonsIncluded in the free Explorer plan

Need the free route first?

Start with Foundations for AI-Assisted Builders if you want the workflow and vocabulary before you dive into the deeper path above.

T

About Tom Hundley

Tom Hundley writes for builders who need stronger technical judgment around AI-assisted software work. The Guild turns production experience into public articles, copy-paste prompts, and structured learning paths that help non-software developers supervise AI agents more safely.

Do this next

Leave this article with one concrete move. Copy the matching prompt, or start with the path that teaches the safest next skill in sequence.