Template
Vercel served 404s: with Hydrogen gone it treated the app as a static Vite site, but TanStack Start's build has no index.html; pages come from its server. Add the hosting adapter TanStack documents for Vercel: - nitro() in vite.config, for 'vite build' only (dev and the nodesandbox runtime never load it); on Vercel it writes .vercel/output with the static assets and one Node.js function running Start + Hono - vercel.json: tanstack-start preset, Yarn 4 via Corepack - 'yarn start' runs the Node build; canonical URLs use the Vercel domain Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
4.3 KiB
Markdown
84 lines
4.3 KiB
Markdown
# Vite Shopify Storefront
|
|
|
|
A server-rendered Shopify storefront built with Vite, TanStack Start (TanStack
|
|
Router + TanStack Query), Hono and Tailwind CSS v4, talking to Shopify's
|
|
[Storefront API](https://shopify.dev/docs/api/storefront) directly over
|
|
GraphQL — no Shopify SDK. It's a port of `nextjs-templates/shopify-storefront`
|
|
without the AI store assistant.
|
|
|
|
Runs in the nodesandbox runtime: `npm install` → `npm run dev` → port 3000.
|
|
|
|
## Getting started
|
|
|
|
```sh
|
|
cp .env.example .env.local # optional; without it the store is mock.shop
|
|
corepack enable # uses the Yarn 4 pinned in package.json
|
|
yarn install
|
|
yarn dev # http://localhost:3000
|
|
```
|
|
|
|
| Script | What it does |
|
|
| ---------------- | --------------------------------------------------------- |
|
|
| `yarn dev` | Vite dev server with SSR and the Hono `/api` routes |
|
|
| `yarn build` | Production build; Nitro packages the server for the host |
|
|
| `yarn start` | Run the Node build from `.output/` |
|
|
| `yarn typecheck` | `tsc` |
|
|
|
|
## Deploying to Vercel
|
|
|
|
Push and deploy — no dashboard settings. `vercel.json` selects the TanStack
|
|
Start preset and installs with Yarn 4 via Corepack. During `vite build` the
|
|
Nitro plugin detects Vercel and writes `.vercel/output/` (static assets plus one
|
|
Node.js function running TanStack Start, with Hono serving `/api/*`). Set
|
|
`VITE_SHOPIFY_*` in the project to use a real store; without them it uses
|
|
mock.shop.
|
|
|
|
## nodesandbox compatibility
|
|
|
|
The sandbox runs Vite's native tools as WebAssembly (`NAPI_RS_FORCE_WASI`), and
|
|
its installer resolves from `package.json` ranges rather than `yarn.lock`. So:
|
|
|
|
- `vite` is pinned to **8.3.2**, which uses rolldown 1.2.x. The runtime must
|
|
support rolldown 1.2's WASI binding (`@emnapi/*` 2.0 / `@napi-rs/wasm-runtime`
|
|
1.2); runtimes that only support rolldown 1.1.x fail to boot with "WASI
|
|
binding not found". Vite 8.1.3 is the last release on rolldown 1.1.x.
|
|
- WASI bindings (`@rolldown/binding-wasm32-wasi`, `@tailwindcss/oxide-wasm32-wasi`)
|
|
are **not** listed here: the runtime installs each package's `*-wasm32-wasi`
|
|
optional dependency itself, and npm on other hosts rejects them
|
|
(`EBADPLATFORM`).
|
|
- `@vitejs/plugin-react` (6.0.0) and Tailwind (4.3.1) match the harness samples.
|
|
- Nitro (the hosting adapter) only loads for `vite build`, never in `vite dev`.
|
|
|
|
## Layout
|
|
|
|
```
|
|
src/
|
|
server.ts Start's server entry: Hono routes /api/*, the rest goes to Start
|
|
router.tsx Router + per-request QueryClient, SSR query integration
|
|
routes/ File routes; loaders prefetch into TanStack Query
|
|
server/
|
|
app.ts Hono API
|
|
account.ts login, logout, register, recover, reset, activate, me
|
|
account.functions.ts server functions for account reads in loaders
|
|
hooks/ TanStack Query options + hooks over the Storefront API
|
|
services/shopify Storefront API client (plain fetch), catalogue and customer functions
|
|
graphql/ Storefront API queries and mutations (`gql()` joins fragments)
|
|
components/ Storefront UI (header, cart drawer, product detail, ...)
|
|
```
|
|
|
|
## How the Next.js pieces map
|
|
|
|
| Next.js | Here |
|
|
| ---------------------------------- | ---------------------------------------------------- |
|
|
| `app/**/page.tsx` | `src/routes/**` (TanStack file routes) |
|
|
| `generateMetadata` / `metadata` | route `head()` via `src/lib/seo.ts`, server-rendered |
|
|
| Server components fetching data | route `loader`s seeding TanStack Query, dehydrated to the client |
|
|
| `app/api/account/*` route handlers | `src/server/account.ts` (Hono) |
|
|
| `next/headers` cookies | `hono/cookie`, and `getCookie` in server functions |
|
|
| `next/image` | `src/components/ui/image.tsx` (Shopify CDN `srcset`) |
|
|
| `NEXT_PUBLIC_*` env | `VITE_*` env (`VITE_SHOPIFY_DOMAIN` defaults to mock.shop) |
|
|
|
|
Cart and catalogue reads after the first page load go straight from the browser
|
|
to the Storefront API with the public token. Account requests stay on the
|
|
server, so the customer access token never reaches client JavaScript.
|