While building Shopify Admin Extensions, a lot of times you would want to fetch data from your server, such as a Remix application, as common. This could lead to one problem: Cross-Origin Resource Sharing or CORS errors. If you were warned with an error like “No Access-Control-Allow-Origin header present”, don’t worry; you are not the only one.
In this blog, we’ll explain what CORS is, why it happens, and how the new Remix app makes handling CORS easier compared to older versions.
What is a CORS Error?
Browsers are strict about security. They don’t allow your web application to fetch data from a server on a different domain unless that server explicitly allows it. For example, if your Shopify Theme app Extension is running from shopify.com and sends requests to fetch data from the Remix app on example.com, then the request will be blocked by the browser unless the server sends a special header like this:
Access-Control-Allow-Origin: *
This security feature is known as CORS and protects users against malicious websites attempting to access sensitive data from other sites.
How Remix Handles CORS?
In older versions of Remix, if your app needed to respond to a cross-origin request, you had to manually add the Access-Control-Allow-Origin header in your loader or action function like this:
export async function loader({ request }) {
const url = new URL(request.url);
const shop = url.searchParams.get('shop');
const products = await prisma.product.findMany({
where: { shop },
});
return json(
{ products },
{
headers: {
"Access-Control-Allow-Origin": "*", // Allow all origins
},
}
);
}
While this works, it adds complexity and increases the chances of making mistakes.
The New Remix App Simplifies Things
The @remix-run/node package now includes improved defaults for handling CORS. In new Remix apps, you no longer need to manually add headers for most use cases. Remix automatically handles common scenarios, making your code cleaner and easier to maintain.
Here’s the same loader function written for the new Remix app:
export async function loader({ request }) {
const url = new URL(request.url);
const shop = url.searchParams.get('shop');
const products = await prisma.product.findMany({
where: { shop },
select: { productId: true, type: true },
});
return json({ products }); // No need for custom headers
}
Notice how much simpler this is! The Remix server handles this for you by setting the correct headers, which allows your Shopify Admin Extension to make requests and get data without worrying about CORS issues.
Why Did Remix Change This?
The Remix team recognized that managing CORS is a repetitive and error-prone task. By handling it automatically, they’ve made development faster and less frustrating. This is especially helpful for apps interacting with external platforms like Shopify.
What You Should Do
For new projects:
If you’re starting a new project with Remix, you don’t need to worry about manually setting CORS headers anymore. Just write your loader and action functions as usual, and let Remix handle the rest.
For existing projects:
Review your current setup
If you’re adding CORS headers manually, test whether you can safely remove them in the new app.
Use the latest Remix version
Update your app to take advantage of these improvements.
Debugging Fetch Requests
If you still encounter CORS issues:
Check the server logs
Ensure your Remix app is running and reachable.
Validate the request
Make sure your Shopify Admin Extension is correctly sending the shop parameter or any required data.
Test locally
Use tools like Postman or your browser’s network tab to inspect requests and responses.
Conclusion
The new Remix app architecture is a game-changer for managing CORS. By removing the need for manual configuration, it simplifies development and reduces errors. Whether you’re building Shopify Theme App Extensions or other apps, you can focus on building features without worrying about cross-origin requests.