Express server in Hydrogen
This recipe transforms a Hydrogen skeleton template to run on a standard Node.js Express server, making it deployable to any Node.js hosting platform instead of Shopify Oxygen. It maintains core Hydrogen functionality including GraphQL codegen and Storefront API integration while replacing Oxygen-specific features with Express equivalents.
Key changes:
- Replaces Oxygen server with Express server
- Uses Vite for development with hot module replacement
- Implements session management through Express middleware
- Provides production-ready server configuration
- Keeps GraphQL codegen functionality intact
Technical details:
- Uses nodemon for development server with automatic restarts
- Environment variables are loaded from .env file using dotenv
- Session management is handled through Express middleware with SESSION_SECRET
- GraphQL codegen still works with Storefront API types
- Compatible with React Router 7.8.x
- The .graphqlrc.ts file is preserved with customer account section commented out
Anchor to RequirementsRequirements
- Node.js 20 or higher (less than 22.0.0) for production deployment
- npm or yarn package manager
- Shopify Storefront API credentials
Anchor to IngredientsIngredients
New files added to the template by this recipe.
| File | Description |
|---|---|
| app/env.ts | Environment type definitions for Express server |
| public/favicon.svg | Favicon for Express template |
| scripts/dev.mjs | Development orchestration script |
| server.mjs | Express server with Hydrogen context and SSR |
Anchor to Step 1: Disable customer account APIStep 1: Disable customer account API
Comment out customer account GraphQL configuration
Anchor to Step 2: Update README for Express deploymentStep 2: Update README for Express deployment
Update README with Express-specific setup and deployment instructions
File
Anchor to Step 3: Add environment type definitionsStep 3: Add environment type definitions
Add environment type definitions for Hydrogen on Express
File
Anchor to Step 4: Set up client-side hydrationStep 4: Set up client-side hydration
Update client entry to use React Router hydration without Oxygen-specific code
Anchor to Step 5: Add the Express template faviconStep 5: Add the Express template favicon
Add Express template favicon
File
Anchor to Step 6: Configure server-side renderingStep 6: Configure server-side rendering
Replace Oxygen server rendering with Express-compatible Node.js SSR using PassThrough streams
File
Anchor to Step 7: Set up the development serverStep 7: Set up the development server
Add development server orchestration script for Vite and nodemon
File
Anchor to Step 8: Simplify the root layoutStep 8: Simplify the root layout
Simplify root layout for Express template by removing complex components
File
Anchor to Step 9: Create the Express serverStep 9: Create the Express server
Add Express server with Hydrogen context, session management, and SSR support
File
Anchor to Step 10: Configure routes for ExpressStep 10: Configure routes for Express
Update routes configuration to work with Hydrogen on Express
Anchor to Step 11: Create a basic homepageStep 11: Create a basic homepage
Simplify homepage route to basic Express example content
File
Anchor to Step 12: Add a minimal product pageStep 12: Add a minimal product page
Simplify product route to minimal implementation without cart functionality
File
Anchor to Step 13: Add basic stylesStep 13: Add basic styles
Replace skeleton styles with minimal Express template styling
File
Anchor to Step 14: Update ESLint configurationStep 14: Update ESLint configuration
Simplify ESLint configuration for Express template
File
Anchor to Step 15: Install Express dependenciesStep 15: Install Express dependencies
Update dependencies and scripts for Express server deployment (add express, nodemon, compression, remove Oxygen packages)
File
Anchor to Step 16: Configure Vite for Node.jsStep 16: Configure Vite for Node. js
Configure Vite for Express deployment with Node.js module externalization
Anchor to Deleted FilesDeleted Files
- templates/skeleton/app/components/AddToCartButton.tsx
- templates/skeleton/app/components/Aside.tsx
- templates/skeleton/app/components/CartLineItem.tsx
- templates/skeleton/app/components/CartMain.tsx
- templates/skeleton/app/components/CartSummary.tsx
- templates/skeleton/app/components/Footer.tsx
- templates/skeleton/app/components/Header.tsx
- templates/skeleton/app/components/PageLayout.tsx
- templates/skeleton/app/components/PaginatedResourceSection.tsx
- templates/skeleton/app/components/ProductForm.tsx
- templates/skeleton/app/components/ProductImage.tsx
- templates/skeleton/app/components/ProductItem.tsx
- templates/skeleton/app/components/ProductPrice.tsx
- templates/skeleton/app/components/SearchForm.tsx
- templates/skeleton/app/components/SearchFormPredictive.tsx
- templates/skeleton/app/components/SearchResults.tsx
- templates/skeleton/app/components/SearchResultsPredictive.tsx
- templates/skeleton/app/graphql/customer-account/CustomerAddressMutations.ts
- templates/skeleton/app/graphql/customer-account/CustomerDetailsQuery.ts
- templates/skeleton/app/graphql/customer-account/CustomerOrderQuery.ts
- templates/skeleton/app/graphql/customer-account/CustomerOrdersQuery.ts
- templates/skeleton/app/graphql/customer-account/CustomerUpdateMutation.ts
- templates/skeleton/app/lib/context.ts
- templates/skeleton/app/lib/fragments.ts
- templates/skeleton/app/lib/redirect.ts
- templates/skeleton/app/lib/search.ts
- templates/skeleton/app/lib/session.ts
- templates/skeleton/app/lib/variants.ts
- templates/skeleton/app/routes/$.tsx
- templates/skeleton/app/routes/[robots.txt].tsx
- templates/skeleton/app/routes/[sitemap.xml].tsx
- templates/skeleton/app/routes/account.$.tsx
- templates/skeleton/app/routes/account._index.tsx
- templates/skeleton/app/routes/account.addresses.tsx
- templates/skeleton/app/routes/account.orders.$id.tsx
- templates/skeleton/app/routes/account.orders._index.tsx
- templates/skeleton/app/routes/account.profile.tsx
- templates/skeleton/app/routes/account.tsx
- templates/skeleton/app/routes/account_.authorize.tsx
- templates/skeleton/app/routes/account_.login.tsx
- templates/skeleton/app/routes/account_.logout.tsx
- templates/skeleton/app/routes/api.$version.[graphql.json].tsx
- templates/skeleton/app/routes/blogs.$blogHandle.$articleHandle.tsx
- templates/skeleton/app/routes/blogs.$blogHandle._index.tsx
- templates/skeleton/app/routes/blogs._index.tsx
- templates/skeleton/app/routes/cart.$lines.tsx
- templates/skeleton/app/routes/cart.tsx
- templates/skeleton/app/routes/collections.$handle.tsx
- templates/skeleton/app/routes/collections._index.tsx
- templates/skeleton/app/routes/collections.all.tsx
- templates/skeleton/app/routes/discount.$code.tsx
- templates/skeleton/app/routes/pages.$handle.tsx
- templates/skeleton/app/routes/policies.$handle.tsx
- templates/skeleton/app/routes/policies._index.tsx
- templates/skeleton/app/routes/search.tsx
- templates/skeleton/app/routes/sitemap.$type.$page[.xml].tsx
- templates/skeleton/app/styles/reset.css
- templates/skeleton/customer-accountapi.generated.d.ts
- templates/skeleton/env.d.ts
- templates/skeleton/server.ts
Anchor to Next stepsNext steps
- Create a
.envfile with your Shopify Storefront API credentials:
- Run
npm installto install Express and other Node.js dependencies - Run
npm run devto start the development server with hot reload - For production, run
npm run buildfollowed bynpm start - Deploy to your preferred Node.js hosting platform (Heroku, AWS, Vercel, Railway, etc.)