Goal: add a contact form to a Hydrogen (Shopify’s React-based custom storefront) that emails submissions, without a built-in Shopify API. Embedding an existing form failed; users asked for low-cost options and whether rebuilding is viable.
Status/updates: A GitHub discussion indicates Shopify devs are working on an example. A community link was shared, but no official solution in thread.
Working approach shared: Implemented with Remix + Conform (form handling) + Zod (validation) + Resend (email service). Create an API route with an action; on submit, post to that route to send an email from a domain you control (for proper Resend setup). Optional: send an automated confirmation email to the customer.
Implementation notes: Add required environment variables and extend TypeScript env.d.ts to avoid type errors. Code screenshots are attached and central to the implementation details.
Open issue: Difficulty retrieving the submission result when the form lives in a different route (e.g., footer in root) than the send action (/contact/send); only “in-flight” status is available via Remix fetcher.
Outcome: Partial solution exists; official example pending. Discussion remains open with unanswered questions about cross-route result handling.
Summarized with AI on December 20.
AI used: gpt-5.
Not sure if this is the place to ask but, is there any way to implement a contact form in a Hydrogen Storefront? I understand there’s no API for it, so I’m just looking for any options without additional cost or too much time.
My requirement is that the form data is sent to an email address.
I tried to embed our current form, but that didn’t work.
It may not be the best solution but I got it working using conform, zod and resend. This is how I normally do it in my Remix projects so figured it was worth a shot in Hydrogen and so far it’s working well. The only thing is I haven’t figured out how to retrieve the result of the submission correctly if the form is not in the same route as your send action (in my case I have my contact form in the footer which is a child of the root route and my send action is in the /contact/send route). Therefore I can only get the “in flight” status from the form fetcher in Remix, not the actual result of the submission. Most likely I’m just missing something so if there is a way to do it let me know!
But if you want to give it a go, just set up an API route with an action and call it on form submission. It needs to come from an email domain that you have control of so you can set it up properly in Resend. So currently a user will submit a form on the business site, the business receives an email (from my agency email account) with the customer enquiry details and then the business can reply to the customer from their email. You can also add an automated email to the customer as well if you want to confirm that their enquiry has been received (which I haven’t done yet, but you would just set up a second email to the customer in the same route action).
The only tricky part in Hydrogen was adding a new environment variable (because I didn’t read the docs at first ) and making sure Typescript didn’t scream at me by extending the env.d.ts once I had pulled the variable from the Shopify storefront.