I’m working on a Shopify Remix app and running into trouble accessing static files from the public folder. I have some data files (like CSV files with product categories) that I need to read inside my main index component.
The problem is that my TSX file can’t seem to find these files even though they’re placed in the /public/ directory. I keep getting parsing errors when trying to fetch them.
Here’s what I’m trying to do:
const categoriesData = await fetch("/product-categories.csv");
But this throws an error:
remix │ Error: Failed to parse URL from /product-categories.csv
I need to load this data so I can process it and inject it into the merchant’s theme as liquid snippets. What’s the proper approach to access static assets like CSV or image files from within a Remix TSX component? Any guidance would be really helpful.
honestly, just move your csv files into the app folder instead of public. i dealt with this same headache last month and wasted hours trying to get the public folder working right. create something like app/data/product-categories.csv and import it directly - way easier than fighting remix’s file serving weirdness.
Fetch fails here because you’re running this server-side without proper URL context. I hit the same issue building a product recommendation feature for a client’s store. Move your file reading logic into a loader function instead of handling it in the component. Create a loader with export async function loader() and use fs.readFile inside it, then grab the data with useLoaderData() in your component. This keeps file system stuff on the server where it belongs and gives your React component clean data. The loader runs before rendering, so your data’s ready when the component mounts.
I encountered a similar issue with my Shopify Remix app. The root of the problem is that fetch doesn’t work with relative URLs server-side due to the absence of a base URL. Instead of using fetch, I found it effective to read files directly with Node.js. You can utilize fs.readFileSync or fs.promises.readFile to access files located in your public directory. For instance, you can use const data = fs.readFileSync(path.join(process.cwd(), 'public', 'product-categories.csv'), 'utf-8'). Remember to import fs and path at the beginning of your file. This approach circumvents the complexities of URLs and simplifies the process of incorporating static files into your liquid snippets.
This happens because Remix’s server-side rendering can’t handle relative URLs in fetch calls. I ran into the same thing building inventory sync tools. Your fetch needs the full URL with protocol and host. Grab it from the request object in your loader: new URL('/product-categories.csv', request.url) instead of just the relative path. Better yet, drop your CSV in the app directory and import it as a module. That kills the URL problem completely and makes your data more predictable since it bundles with your code instead of sitting as a static asset.
This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.