# 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 to `dist/` | | `yarn typecheck` | `tsc` | ## 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. - No Nitro. ## 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.