+
{/* Header owns the cart drawer, search and account menu, so every
route gets them by rendering here rather than page by page. */}
{
const customer = await queryClient
.fetchQuery(customerQueryOptions())
diff --git a/src/routes/api/$.ts b/src/routes/api/$.ts
new file mode 100644
index 0000000..36410f0
--- /dev/null
+++ b/src/routes/api/$.ts
@@ -0,0 +1,18 @@
+import { createFileRoute } from '@tanstack/react-router';
+import api from '@/server/app';
+
+// Every /api/* request goes to the Hono app (src/server/app.ts), which owns
+// the customer-account endpoints and their session cookie.
+const handle = ({ request }: { request: Request }) => api.fetch(request);
+
+export const Route = createFileRoute('/api/$')({
+ server: {
+ handlers: {
+ GET: handle,
+ POST: handle,
+ PUT: handle,
+ PATCH: handle,
+ DELETE: handle,
+ },
+ },
+});
diff --git a/src/routes/collections/index.tsx b/src/routes/collections/index.tsx
index 7af5346..7f88602 100644
--- a/src/routes/collections/index.tsx
+++ b/src/routes/collections/index.tsx
@@ -1,8 +1,13 @@
import { createFileRoute } from '@tanstack/react-router';
import Collections from '@/components/shopify/collections';
+import { collectionsQueryOptions } from '@/hooks/use-shopify-collections';
import { seo } from '@/lib/seo';
export const Route = createFileRoute('/collections/')({
+ loader: ({ context: { queryClient } }) =>
+ queryClient
+ .ensureQueryData(collectionsQueryOptions(12))
+ .then(() => undefined, () => undefined),
head: () =>
seo({
title: 'Collections',
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index 68de000..18fbb10 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -1,9 +1,16 @@
import { createFileRoute } from '@tanstack/react-router';
import Products from '@/components/shopify/products';
+import { productsInfiniteQueryOptions } from '@/hooks/use-shopify-products';
import { site } from '@/config/site';
import { seo } from '@/lib/seo';
export const Route = createFileRoute('/')({
+ // Server-render the first page of products; the grid reads the same query.
+ // A failure falls through to the grid's own error state.
+ loader: ({ context: { queryClient } }) =>
+ queryClient
+ .ensureInfiniteQueryData(productsInfiniteQueryOptions({ first: 12 }))
+ .then(() => undefined, () => undefined),
// The home page keeps the bare store name rather than "Shop — Shop".
head: () => seo({ title: site.storeName, absolute: true, path: '/' }),
component: () => (
diff --git a/src/routes/search.tsx b/src/routes/search.tsx
index d9755d0..061b2d9 100644
--- a/src/routes/search.tsx
+++ b/src/routes/search.tsx
@@ -1,5 +1,6 @@
import { createFileRoute } from '@tanstack/react-router';
import SearchResults from '@/components/shopify/search-results';
+import { searchInfiniteQueryOptions } from '@/hooks/use-shopify-search';
import { seo } from '@/lib/seo';
interface SearchParams {
@@ -10,6 +11,12 @@ export const Route = createFileRoute('/search')({
validateSearch: (search: Record): SearchParams => ({
q: typeof search.q === 'string' && search.q ? search.q : undefined,
}),
+ loaderDeps: ({ search: { q } }) => ({ q }),
+ // First page for the default sort and no filters, matching SearchResults.
+ loader: ({ deps: { q }, context: { queryClient } }) =>
+ queryClient
+ .ensureInfiniteQueryData(searchInfiniteQueryOptions({ query: q ?? '' }))
+ .then(() => undefined, () => undefined),
head: () =>
seo({
title: 'Search',
diff --git a/src/routes/shop/collections.tsx b/src/routes/shop/collections.tsx
index e832785..79404e5 100644
--- a/src/routes/shop/collections.tsx
+++ b/src/routes/shop/collections.tsx
@@ -1,8 +1,13 @@
import { createFileRoute } from '@tanstack/react-router';
import Collections from '@/components/shopify/collections';
+import { collectionsQueryOptions } from '@/hooks/use-shopify-collections';
import { seo } from '@/lib/seo';
export const Route = createFileRoute('/shop/collections')({
+ loader: ({ context: { queryClient } }) =>
+ queryClient
+ .ensureQueryData(collectionsQueryOptions(12))
+ .then(() => undefined, () => undefined),
head: () =>
seo({
title: 'Collections',
diff --git a/src/server/account.functions.ts b/src/server/account.functions.ts
new file mode 100644
index 0000000..4ea5cd9
--- /dev/null
+++ b/src/server/account.functions.ts
@@ -0,0 +1,36 @@
+// Server functions for account reads made by route loaders. Loaders run on the
+// server during SSR, where `fetch('/api/...')` has neither an origin nor the
+// visitor's cookies, so these read the session directly instead.
+import { createServerFn } from '@tanstack/react-start';
+import { getCookie } from '@tanstack/react-start/server';
+import {
+ CUSTOMER_TOKEN_COOKIE,
+ getCustomer,
+} from '@/services/shopify/customer';
+
+// Minimal session probe for the header menu — never returns the token.
+export const getSessionCustomer = createServerFn({ method: 'GET' }).handler(
+ async () => {
+ const token = getCookie(CUSTOMER_TOKEN_COOKIE);
+ if (!token) return null;
+
+ const customer = await getCustomer(token, 0);
+ if (!customer) return null;
+
+ return {
+ displayName: customer.displayName,
+ email: customer.email,
+ firstName: customer.firstName,
+ };
+ }
+);
+
+// Full profile with recent orders, for the order history page.
+export const getAccountCustomer = createServerFn({ method: 'GET' }).handler(
+ async () => {
+ const token = getCookie(CUSTOMER_TOKEN_COOKIE);
+ if (!token) return null;
+
+ return getCustomer(token, 20);
+ }
+);
diff --git a/server/account.ts b/src/server/account.ts
similarity index 93%
rename from server/account.ts
rename to src/server/account.ts
index 0b45350..8489264 100644
--- a/server/account.ts
+++ b/src/server/account.ts
@@ -43,15 +43,6 @@ account.get('/me', async (c) => {
});
});
-// Full profile with recent orders, for the order history page.
-account.get('/customer', async (c) => {
- const token = getSessionToken(c);
- if (!token) return c.json({ customer: null });
-
- const customer = await getCustomer(token, 20);
- return c.json({ customer });
-});
-
account.post('/login', async (c) => {
const { email, password } = await readBody(c.req.raw);
diff --git a/server/app.ts b/src/server/app.ts
similarity index 70%
rename from server/app.ts
rename to src/server/app.ts
index 6b27e02..0bac6f4 100644
--- a/server/app.ts
+++ b/src/server/app.ts
@@ -1,5 +1,4 @@
-// The API surface. In dev, @hono/vite-dev-server mounts this inside Vite; in
-// production, server/node.ts serves it alongside the built client.
+// The API surface, mounted by the Start server route in routes/api/$.ts.
import { Hono } from 'hono';
import { account } from './account';
diff --git a/server/session.ts b/src/server/session.ts
similarity index 100%
rename from server/session.ts
rename to src/server/session.ts
diff --git a/tsconfig.json b/tsconfig.json
index c20cb1a..06da9e3 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,6 +17,6 @@
"@/*": ["./src/*"]
}
},
- "include": ["src", "server", "vite.config.ts"],
- "exclude": ["node_modules", "dist"]
+ "include": ["src", "vite.config.ts"],
+ "exclude": ["node_modules", "dist", ".output"]
}
diff --git a/vercel.json b/vercel.json
new file mode 100644
index 0000000..4ec2022
--- /dev/null
+++ b/vercel.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://openapi.vercel.sh/vercel.json",
+ "framework": "tanstack-start",
+ "installCommand": "corepack enable && yarn install",
+ "buildCommand": "yarn build"
+}
diff --git a/vite.config.ts b/vite.config.ts
index 1a842e0..cc18921 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,30 +1,36 @@
import { defineConfig } from 'vite';
+import { tanstackStart } from '@tanstack/react-start/plugin/vite';
+import { nitro } from 'nitro/vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
-import { tanstackRouter } from '@tanstack/router-plugin/vite';
-import devServer from '@hono/vite-dev-server';
import { fileURLToPath, URL } from 'node:url';
+// Absolute origin for canonical and Open Graph URLs. Inlined at build time so
+// the server render and the client agree on it. Vercel provides the production
+// domain; set VITE_SITE_URL to override it anywhere.
+const siteUrl =
+ process.env.VITE_SITE_URL ??
+ (process.env.VERCEL_PROJECT_PRODUCTION_URL
+ ? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
+ : 'http://localhost:3000');
+
export default defineConfig({
+ server: { port: 3000 },
plugins: [
- // Must run before the React plugin so the generated route tree is in place.
- tanstackRouter({ target: 'react', autoCodeSplitting: true }),
+ // Start must come before the React plugin.
+ tanstackStart(),
+ // Builds the server for the host: Vercel's Build Output when deployed
+ // there, a standalone Node server (.output/) everywhere else.
+ nitro(),
react(),
tailwindcss(),
- // Serves the Hono API in dev. Everything outside /api falls through to
- // Vite, which serves the SPA.
- devServer({
- entry: 'server/app.ts',
- exclude: [/^(?!\/api(\/|$)).*/],
- injectClientScript: false,
- }),
],
+ define: {
+ 'import.meta.env.VITE_SITE_URL': JSON.stringify(siteUrl),
+ },
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
- build: {
- outDir: 'dist/client',
- },
});
diff --git a/yarn.lock b/yarn.lock
index 175218e..d8f4068 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -30,7 +30,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/code-frame@npm:^7.29.7":
+"@babel/code-frame@npm:7.29.7, @babel/code-frame@npm:^7.29.7":
version: 7.29.7
resolution: "@babel/code-frame@npm:7.29.7"
dependencies:
@@ -331,45 +331,6 @@ __metadata:
languageName: node
linkType: hard
-"@hono/node-server@npm:^1.19.11":
- version: 1.19.17
- resolution: "@hono/node-server@npm:1.19.17"
- peerDependencies:
- hono: ^4
- checksum: 10c0/e77907e3b5db8ab68ed4f297ad84807bfdd698636408de86ab8d36dab4658504ac4c0ed9d9436bc272a0172b9b7a5a4b578532e0b5baf97674c7b420cb5cff4b
- languageName: node
- linkType: hard
-
-"@hono/node-server@npm:^2.1.3":
- version: 2.1.3
- resolution: "@hono/node-server@npm:2.1.3"
- peerDependencies:
- hono: ^4
- checksum: 10c0/1b9996f41be620c301f73529928ccb056574fadf822a0979e4925c17cce209583e7f27376ae2308b4e87ab6c1c7501d6f282333c364ed79f21b99b45b47f7ffb
- languageName: node
- linkType: hard
-
-"@hono/vite-dev-server@npm:^0.26.1":
- version: 0.26.1
- resolution: "@hono/vite-dev-server@npm:0.26.1"
- dependencies:
- "@hono/node-server": "npm:^1.19.11"
- minimatch: "npm:^9.0.3"
- peerDependencies:
- hono: "*"
- miniflare: "*"
- wrangler: "*"
- peerDependenciesMeta:
- hono:
- optional: false
- miniflare:
- optional: true
- wrangler:
- optional: true
- checksum: 10c0/235334d35c1f6345a7e874191c2a18f2e2018a0713ed8fcef5f0c9aa3097fc0cc15ae6bb95f9536b75fc4b5b1bf4421140e857ffaa87029c4b692c893caa9a2b
- languageName: node
- linkType: hard
-
"@isaacs/fs-minipass@npm:^4.0.0":
version: 4.0.1
resolution: "@isaacs/fs-minipass@npm:4.0.1"
@@ -435,6 +396,43 @@ __metadata:
languageName: node
linkType: hard
+"@oozcitak/dom@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "@oozcitak/dom@npm:2.0.2"
+ dependencies:
+ "@oozcitak/infra": "npm:^2.0.2"
+ "@oozcitak/url": "npm:^3.0.0"
+ "@oozcitak/util": "npm:^10.0.0"
+ checksum: 10c0/053dfec09c6b5a38e2deb601f97313e01184a2c6452c13767a9629aa6686749f6f9d230806c51ab213dd454465b9e0f403cb7c45e210b447d5fe059a780278cf
+ languageName: node
+ linkType: hard
+
+"@oozcitak/infra@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "@oozcitak/infra@npm:2.0.2"
+ dependencies:
+ "@oozcitak/util": "npm:^10.0.0"
+ checksum: 10c0/26392f3cc6c0787b9256e1eaa39a4dc374dc54f437ea1e8d3314fb41f7bc2c011c3c3eac7bc58b1773968df0c2991ca41761aa12778a0ca4059f0a79002b6205
+ languageName: node
+ linkType: hard
+
+"@oozcitak/url@npm:^3.0.0":
+ version: 3.0.0
+ resolution: "@oozcitak/url@npm:3.0.0"
+ dependencies:
+ "@oozcitak/infra": "npm:^2.0.2"
+ "@oozcitak/util": "npm:^10.0.0"
+ checksum: 10c0/0a43eb9db072078f0826ea5eeefd5c398e4e47aa6f99a09b87724eed3bf018894de3e6617631547df194ec0ceb965cd5feb9bf666eb094952fed1280770b4f7a
+ languageName: node
+ linkType: hard
+
+"@oozcitak/util@npm:^10.0.0":
+ version: 10.0.0
+ resolution: "@oozcitak/util@npm:10.0.0"
+ checksum: 10c0/4f143f50779790166e747c722383551af819776e7f946c9bd25b9875a128c517c91f058fb4ea11b235388eea83bf7b84a5590f882c74171e95b04487bc2b948d
+ languageName: node
+ linkType: hard
+
"@oxc-project/types@npm:=0.152.0":
version: 0.152.0
resolution: "@oxc-project/types@npm:0.152.0"
@@ -2047,7 +2045,7 @@ __metadata:
languageName: node
linkType: hard
-"@tanstack/query-core@npm:5.104.1":
+"@tanstack/query-core@npm:5.104.1, @tanstack/query-core@npm:^5.104.1":
version: 5.104.1
resolution: "@tanstack/query-core@npm:5.104.1"
checksum: 10c0/d42788e0c9ee4a389d7de21c5fe856acd50d24f72cc87b3c76e6852399ab9835801f415d0a9e10706d2a3a27937d42c5f1ac621ceeac21e6bcd60aa87984bdf4
@@ -2065,7 +2063,22 @@ __metadata:
languageName: node
linkType: hard
-"@tanstack/react-router@npm:^1.170.41":
+"@tanstack/react-router-ssr-query@npm:^1.167.3":
+ version: 1.167.3
+ resolution: "@tanstack/react-router-ssr-query@npm:1.167.3"
+ dependencies:
+ "@tanstack/router-ssr-query-core": "npm:1.169.3"
+ peerDependencies:
+ "@tanstack/query-core": ">=5.102.0"
+ "@tanstack/react-query": ">=5.102.0"
+ "@tanstack/react-router": ">=1.170.33"
+ react: ">=18.0.0 || >=19.0.0"
+ react-dom: ">=18.0.0 || >=19.0.0"
+ checksum: 10c0/242a1f98660d8b9d6d474a5177234b26c24a87de015ab8592654581f9b49538f1010e15183d94491680d00a6a7627ac345c9b38c5420d5dba50ca8ddc7d39a38
+ languageName: node
+ linkType: hard
+
+"@tanstack/react-router@npm:1.170.41, @tanstack/react-router@npm:^1.170.41":
version: 1.170.41
resolution: "@tanstack/react-router@npm:1.170.41"
dependencies:
@@ -2080,6 +2093,92 @@ __metadata:
languageName: node
linkType: hard
+"@tanstack/react-start-client@npm:1.168.39":
+ version: 1.168.39
+ resolution: "@tanstack/react-start-client@npm:1.168.39"
+ dependencies:
+ "@tanstack/react-router": "npm:1.170.41"
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/start-client-core": "npm:1.170.34"
+ peerDependencies:
+ react: ">=18.0.0 || >=19.0.0"
+ react-dom: ">=18.0.0 || >=19.0.0"
+ checksum: 10c0/710142fcaaaef7ed40c26bd2b874c5cbe5544d57ce2134d226a4057742b0c276c6d92902b119abae07d1a53ed95d3dabe2fca47c4d844390052889c671658b48
+ languageName: node
+ linkType: hard
+
+"@tanstack/react-start-rsc@npm:0.1.59":
+ version: 0.1.59
+ resolution: "@tanstack/react-start-rsc@npm:0.1.59"
+ dependencies:
+ "@tanstack/react-router": "npm:1.170.41"
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/router-utils": "npm:1.162.3"
+ "@tanstack/start-client-core": "npm:1.170.34"
+ "@tanstack/start-fn-stubs": "npm:1.162.0"
+ "@tanstack/start-plugin-core": "npm:1.171.49"
+ "@tanstack/start-storage-context": "npm:1.167.36"
+ pathe: "npm:^2.0.3"
+ peerDependencies:
+ "@rspack/core": ">=2.0.0-0"
+ "@vitejs/plugin-rsc": ">=0.5.30"
+ react: ">=18.0.0 || >=19.0.0"
+ react-dom: ">=18.0.0 || >=19.0.0"
+ react-server-dom-rspack: ">=0.0.2"
+ peerDependenciesMeta:
+ "@rspack/core":
+ optional: true
+ "@vitejs/plugin-rsc":
+ optional: true
+ react-server-dom-rspack:
+ optional: true
+ checksum: 10c0/251068c34d35bac4002d3824fe7fb6d0fd1807de27c7c9befa5b9c0ebd698f67f862ec0d05d6f652f8d9f2af59af6d2fdb77568dfd20a9a6c432238e5bac2379
+ languageName: node
+ linkType: hard
+
+"@tanstack/react-start-server@npm:1.167.46":
+ version: 1.167.46
+ resolution: "@tanstack/react-start-server@npm:1.167.46"
+ dependencies:
+ "@tanstack/react-router": "npm:1.170.41"
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/start-server-core": "npm:1.169.39"
+ peerDependencies:
+ react: ">=18.0.0 || >=19.0.0"
+ react-dom: ">=18.0.0 || >=19.0.0"
+ checksum: 10c0/6d016f0749e1f3d4f9a11b68b287b99e9cb4fe16f1cdb76525f1d3d5e048e96cd8a3c95348ab4b254a32d83a379e75a5274eb0b6be5acb23765157400052950e
+ languageName: node
+ linkType: hard
+
+"@tanstack/react-start@npm:^1.168.60":
+ version: 1.168.60
+ resolution: "@tanstack/react-start@npm:1.168.60"
+ dependencies:
+ "@tanstack/react-router": "npm:1.170.41"
+ "@tanstack/react-start-client": "npm:1.168.39"
+ "@tanstack/react-start-rsc": "npm:0.1.59"
+ "@tanstack/react-start-server": "npm:1.167.46"
+ "@tanstack/router-utils": "npm:1.162.3"
+ "@tanstack/start-client-core": "npm:1.170.34"
+ "@tanstack/start-plugin-core": "npm:1.171.49"
+ "@tanstack/start-server-core": "npm:1.169.39"
+ pathe: "npm:^2.0.3"
+ peerDependencies:
+ "@rsbuild/core": ^2.0.0
+ react: ">=18.0.0 || >=19.0.0"
+ react-dom: ">=18.0.0 || >=19.0.0"
+ vite: ">=7.0.0"
+ peerDependenciesMeta:
+ "@rsbuild/core":
+ optional: true
+ "@vitejs/plugin-rsc":
+ optional: true
+ vite:
+ optional: true
+ checksum: 10c0/905c23a737775e88937f8fdd1f6bdf468f5c21bdc2d88712148435246eb0eb1d5d90d083878988404be25573b4e3284fb8a391efdbc0d33195891090bfd8ab3d
+ languageName: node
+ linkType: hard
+
"@tanstack/react-store@npm:^0.11.2":
version: 0.11.2
resolution: "@tanstack/react-store@npm:0.11.2"
@@ -2121,7 +2220,7 @@ __metadata:
languageName: node
linkType: hard
-"@tanstack/router-plugin@npm:^1.168.42":
+"@tanstack/router-plugin@npm:1.168.42":
version: 1.168.42
resolution: "@tanstack/router-plugin@npm:1.168.42"
dependencies:
@@ -2155,6 +2254,16 @@ __metadata:
languageName: node
linkType: hard
+"@tanstack/router-ssr-query-core@npm:1.169.3":
+ version: 1.169.3
+ resolution: "@tanstack/router-ssr-query-core@npm:1.169.3"
+ peerDependencies:
+ "@tanstack/query-core": ">=5.102.0"
+ "@tanstack/router-core": ">=1.171.28"
+ checksum: 10c0/c5e77b2ac7697d8f35b1515e2f8a29526aecde48ff23aa00a70f43970cb6b02887c9e034eadb91c9d405d87ecf88a53595c0e42a342411bb64d5ddce1a808860
+ languageName: node
+ linkType: hard
+
"@tanstack/router-utils@npm:1.162.3":
version: 1.162.3
resolution: "@tanstack/router-utils@npm:1.162.3"
@@ -2171,6 +2280,86 @@ __metadata:
languageName: node
linkType: hard
+"@tanstack/start-client-core@npm:1.170.34":
+ version: 1.170.34
+ resolution: "@tanstack/start-client-core@npm:1.170.34"
+ dependencies:
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/start-fn-stubs": "npm:1.162.0"
+ "@tanstack/start-storage-context": "npm:1.167.36"
+ seroval: "npm:^1.6.7"
+ checksum: 10c0/f11adf1514db4f9dec7f8a78bb76fc3eb063724ba1ad74e03eadac4f3611743300ec47ca3775feecc3f67d67de08630542ffcda2bbae0f9239e34706af0aff97
+ languageName: node
+ linkType: hard
+
+"@tanstack/start-fn-stubs@npm:1.162.0":
+ version: 1.162.0
+ resolution: "@tanstack/start-fn-stubs@npm:1.162.0"
+ checksum: 10c0/74a29594f38204e547871d201abf6dd297adf58754ed39ef8fa2a6bea6a2999386445023e50dba8fbe013bbb08f5d5cbd3f96b9301e6a8c8e4cf6047c24ca1f0
+ languageName: node
+ linkType: hard
+
+"@tanstack/start-plugin-core@npm:1.171.49":
+ version: 1.171.49
+ resolution: "@tanstack/start-plugin-core@npm:1.171.49"
+ dependencies:
+ "@babel/code-frame": "npm:7.29.7"
+ "@babel/core": "npm:^7.29.7"
+ "@babel/types": "npm:^7.29.8"
+ "@jridgewell/remapping": "npm:^2.3.5"
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/router-generator": "npm:1.167.40"
+ "@tanstack/router-plugin": "npm:1.168.42"
+ "@tanstack/router-utils": "npm:1.162.3"
+ "@tanstack/start-server-core": "npm:1.169.39"
+ exsolve: "npm:^1.1.1"
+ lightningcss: "npm:^1.33.0"
+ pathe: "npm:^2.0.3"
+ picomatch: "npm:^4.0.7"
+ seroval: "npm:^1.6.7"
+ source-map: "npm:^0.7.6"
+ srvx: "npm:^0.11.22"
+ tinyglobby: "npm:^0.2.17"
+ ufo: "npm:^1.6.4"
+ vitefu: "npm:^1.1.3"
+ xmlbuilder2: "npm:^4.0.3"
+ zod: "npm:^4.5.4"
+ peerDependencies:
+ "@rsbuild/core": ^2.0.0
+ vite: ">=7.0.0"
+ peerDependenciesMeta:
+ "@rsbuild/core":
+ optional: true
+ vite:
+ optional: true
+ checksum: 10c0/c10e2bcbb70661fda8ce3e3f273b1904600e6b0d45d6f50b5c52a5e72148a153e6d43a7a28411415729b19a29367cf76b07ee68bfafe0484f3717e5f358e0096
+ languageName: node
+ linkType: hard
+
+"@tanstack/start-server-core@npm:1.169.39":
+ version: 1.169.39
+ resolution: "@tanstack/start-server-core@npm:1.169.39"
+ dependencies:
+ "@tanstack/history": "npm:1.162.4"
+ "@tanstack/router-core": "npm:1.171.34"
+ "@tanstack/start-client-core": "npm:1.170.34"
+ "@tanstack/start-storage-context": "npm:1.167.36"
+ fetchdts: "npm:^0.1.6"
+ h3-v2: "npm:h3@2.0.1-rc.20"
+ seroval: "npm:^1.6.7"
+ checksum: 10c0/fd4d123eabb5fbaa07f2a6a2fc03d6244114e9214d0c3ad46a60f6c8223dffe9e11907ec08adbc63a7829f7ad10f150caf829ac674db85d6290f5ba6e7adc14b
+ languageName: node
+ linkType: hard
+
+"@tanstack/start-storage-context@npm:1.167.36":
+ version: 1.167.36
+ resolution: "@tanstack/start-storage-context@npm:1.167.36"
+ dependencies:
+ "@tanstack/router-core": "npm:1.171.34"
+ checksum: 10c0/7714b8dbc41c7820542d264f38c2225991811ccb51254b88880ffb8d63ffa478c266a3edc7a78d1b2c6d813de0b0269de7bed63549322dd274d2143860680fce
+ languageName: node
+ linkType: hard
+
"@tanstack/store@npm:0.11.2":
version: 0.11.2
resolution: "@tanstack/store@npm:0.11.2"
@@ -2256,6 +2445,13 @@ __metadata:
languageName: node
linkType: hard
+"argparse@npm:^2.0.1":
+ version: 2.0.1
+ resolution: "argparse@npm:2.0.1"
+ checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e
+ languageName: node
+ linkType: hard
+
"aria-hidden@npm:^1.2.4":
version: 1.2.6
resolution: "aria-hidden@npm:1.2.6"
@@ -2277,13 +2473,6 @@ __metadata:
languageName: node
linkType: hard
-"balanced-match@npm:^1.0.0":
- version: 1.0.2
- resolution: "balanced-match@npm:1.0.2"
- checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee
- languageName: node
- linkType: hard
-
"baseline-browser-mapping@npm:^2.11.26":
version: 2.11.27
resolution: "baseline-browser-mapping@npm:2.11.27"
@@ -2293,15 +2482,6 @@ __metadata:
languageName: node
linkType: hard
-"brace-expansion@npm:^2.0.2":
- version: 2.1.7
- resolution: "brace-expansion@npm:2.1.7"
- dependencies:
- balanced-match: "npm:^1.0.0"
- checksum: 10c0/17ee4194c85b05cde0a7b7c068eeef664440c027116ef42c3d35c13ebabdc9fd3eaf05c5c8a06dd0ca20ae012d652561d8ac2a699daa5cbee1f0510e5134ab4d
- languageName: node
- linkType: hard
-
"browserslist@npm:^4.24.0":
version: 4.29.3
resolution: "browserslist@npm:4.29.3"
@@ -2371,6 +2551,13 @@ __metadata:
languageName: node
linkType: hard
+"consola@npm:^3.4.2":
+ version: 3.4.2
+ resolution: "consola@npm:3.4.2"
+ checksum: 10c0/7cebe57ecf646ba74b300bcce23bff43034ed6fbec9f7e39c27cee1dc00df8a21cd336b466ad32e304ea70fba04ec9e890c200270de9a526ce021ba8a7e4c11a
+ languageName: node
+ linkType: hard
+
"convert-source-map@npm:^2.0.0":
version: 2.0.0
resolution: "convert-source-map@npm:2.0.0"
@@ -2385,6 +2572,18 @@ __metadata:
languageName: node
linkType: hard
+"crossws@npm:^0.4.12":
+ version: 0.4.12
+ resolution: "crossws@npm:0.4.12"
+ peerDependencies:
+ srvx: ">=0.11.5"
+ peerDependenciesMeta:
+ srvx:
+ optional: true
+ checksum: 10c0/28d95429d666e2b925ccdc1c2f01ad23de21b7a8772cf063281127b9eea4a1b80c459f8404957d7231609750ff81ed6a6514e9c393a3130f35919e7a98a854ce
+ languageName: node
+ linkType: hard
+
"csstype@npm:^3.2.2":
version: 3.2.3
resolution: "csstype@npm:3.2.3"
@@ -2392,6 +2591,13 @@ __metadata:
languageName: node
linkType: hard
+"db0@npm:^0.4.1":
+ version: 0.4.1
+ resolution: "db0@npm:0.4.1"
+ checksum: 10c0/2f965e59496455e2c8105f7f17bbbb8a93aefbe6d023cb6670ccba4757ee3ea99ae45be9b190ce87a98257d75a11fa98d1fbe506757360f7dc57adb9465c953e
+ languageName: node
+ linkType: hard
+
"debug@npm:^4.1.0, debug@npm:^4.3.1":
version: 4.4.3
resolution: "debug@npm:4.4.3"
@@ -2449,6 +2655,20 @@ __metadata:
languageName: node
linkType: hard
+"env-runner@npm:^0.2.1":
+ version: 0.2.3
+ resolution: "env-runner@npm:0.2.3"
+ dependencies:
+ crossws: "npm:^0.4.12"
+ exsolve: "npm:^1.1.1"
+ httpxy: "npm:^0.5.5"
+ srvx: "npm:^1.0.5"
+ bin:
+ env-runner: ./dist/cli.mjs
+ checksum: 10c0/b72e0cf4dc17257b963c4dd265749bf68eea721558d82bcedb7b0684d946c8624b8c57949485f54bef86fea92a3fe5abce66cd1e3b70abcb8177950079fb5f0d
+ languageName: node
+ linkType: hard
+
"escalade@npm:^3.2.0":
version: 3.2.0
resolution: "escalade@npm:3.2.0"
@@ -2463,6 +2683,13 @@ __metadata:
languageName: node
linkType: hard
+"exsolve@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "exsolve@npm:1.1.1"
+ checksum: 10c0/0b157a7600408bd356ff78cff5ad9c8c0dd7ca5e7f246216c3c9b66196e76277d3130021122b9c5078a3462751fd7aa988fe3dc1e3b80c79cb873c1623f628e1
+ languageName: node
+ linkType: hard
+
"fdir@npm:^6.5.0":
version: 6.5.0
resolution: "fdir@npm:6.5.0"
@@ -2475,6 +2702,13 @@ __metadata:
languageName: node
linkType: hard
+"fetchdts@npm:^0.1.6":
+ version: 0.1.7
+ resolution: "fetchdts@npm:0.1.7"
+ checksum: 10c0/7497671ee28b3e7cc49d037a7c11e6f98e53e6e2abd85f26e8fac3fae4142c3c0d91352dc46198530f73b16480585605c63e3d112c34210ff2c75be1199668a0
+ languageName: node
+ linkType: hard
+
"framer-motion@npm:^12.42.2":
version: 12.43.0
resolution: "framer-motion@npm:12.43.0"
@@ -2554,13 +2788,50 @@ __metadata:
languageName: node
linkType: hard
-"graphql@npm:^15.5.0 || ^16.0.0 || ^17.0.0":
+"graphql@npm:^15.5.0 || ^16.0.0 || ^17.0.0, graphql@npm:^17.0.2":
version: 17.0.2
resolution: "graphql@npm:17.0.2"
checksum: 10c0/766546216b891439ed09fd8584963df2013e26f2f79f096036eaaa2788c38964e049c8a142d68e3afdabdd8bbe70042639e83f0f4b82edbc7c6850421f072bb6
languageName: node
linkType: hard
+"h3-v2@npm:h3@2.0.1-rc.20":
+ version: 2.0.1-rc.20
+ resolution: "h3@npm:2.0.1-rc.20"
+ dependencies:
+ rou3: "npm:^0.8.1"
+ srvx: "npm:^0.11.13"
+ peerDependencies:
+ crossws: ^0.4.1
+ peerDependenciesMeta:
+ crossws:
+ optional: true
+ bin:
+ h3: bin/h3.mjs
+ checksum: 10c0/9bc662b9b61450625cacb9dcbe8c6d3b86281090f3816ea6c70fad854a24dbb7dcb3450c987f00e71960ee930daf95453253a855c5e1ea8a13e3cd7c3b2113f6
+ languageName: node
+ linkType: hard
+
+"h3@npm:^2.0.1-rc.31":
+ version: 2.0.1-rc.32
+ resolution: "h3@npm:2.0.1-rc.32"
+ dependencies:
+ rou3: "npm:^0.9.2"
+ srvx: "npm:^1.0.5"
+ peerDependencies:
+ crossws: ^0.4.12
+ ocache: ">=0.3.0"
+ peerDependenciesMeta:
+ crossws:
+ optional: true
+ ocache:
+ optional: true
+ bin:
+ h3: ./bin/h3.mjs
+ checksum: 10c0/182881ebf9c866f79ca120e8bc1b8a8850c34673758b67593fed7217cf04387294241e63397e20dd690c39cad05c6ce070eefc0707d7813ecfa9e358c66edd59
+ languageName: node
+ linkType: hard
+
"hono@npm:^4.13.12":
version: 4.13.12
resolution: "hono@npm:4.13.12"
@@ -2568,6 +2839,20 @@ __metadata:
languageName: node
linkType: hard
+"hookable@npm:^6.1.1":
+ version: 6.1.2
+ resolution: "hookable@npm:6.1.2"
+ checksum: 10c0/ea5cdb1b1a1919b48cfbbfb55c8009f6843473ff50f67d6e959fd291cb2fd0a4934e85124bfd6531b1d2edf1e0675bc5954f85a12318a59b15c7a3e5667f0d4e
+ languageName: node
+ linkType: hard
+
+"httpxy@npm:^0.5.5":
+ version: 0.5.5
+ resolution: "httpxy@npm:0.5.5"
+ checksum: 10c0/7be52cbfbd4157b4ac3aa22124d06081e8ffc50a185622e43c0ce8229bbcd7411d016f4a364fecb694325ed312823efbf51c70fa8049563a8b6b617642914cd3
+ languageName: node
+ linkType: hard
+
"isbot@npm:^5.1.22":
version: 5.2.2
resolution: "isbot@npm:5.2.2"
@@ -2598,6 +2883,17 @@ __metadata:
languageName: node
linkType: hard
+"js-yaml@npm:^4.1.1":
+ version: 4.3.2
+ resolution: "js-yaml@npm:4.3.2"
+ dependencies:
+ argparse: "npm:^2.0.1"
+ bin:
+ js-yaml: bin/js-yaml.js
+ checksum: 10c0/dedd34c2e8fef1d504687f1bc94ed0ee1311a1f78770fa2800352c6d59c635ccf555009d74e9afe529ae62199da2b1ccef30e53dc84dcd8d2d8187c22574bc97
+ languageName: node
+ linkType: hard
+
"jsesc@npm:^3.0.2":
version: 3.1.0
resolution: "jsesc@npm:3.1.0"
@@ -2883,15 +3179,6 @@ __metadata:
languageName: node
linkType: hard
-"minimatch@npm:^9.0.3":
- version: 9.0.9
- resolution: "minimatch@npm:9.0.9"
- dependencies:
- brace-expansion: "npm:^2.0.2"
- checksum: 10c0/0b6a58530dbb00361745aa6c8cffaba4c90f551afe7c734830bd95fd88ebf469dd7355a027824ea1d09e37181cfeb0a797fb17df60c15ac174303ac110eb7e86
- languageName: node
- linkType: hard
-
"minipass@npm:^7.0.4, minipass@npm:^7.1.2":
version: 7.1.3
resolution: "minipass@npm:7.1.3"
@@ -2940,6 +3227,36 @@ __metadata:
languageName: node
linkType: hard
+"nf3@npm:^0.3.24":
+ version: 0.3.24
+ resolution: "nf3@npm:0.3.24"
+ checksum: 10c0/6c971b63634b6f7838194b5266fb40a8cb763d55a83b07a58ec3cf044fba1eef2fddfb6ee4d760ac3fbda34f69b9c04ddb923505cff3bbb57b7836c33c54b8ed
+ languageName: node
+ linkType: hard
+
+"nitro@npm:3.0.260903-beta":
+ version: 3.0.260903-beta
+ resolution: "nitro@npm:3.0.260903-beta"
+ dependencies:
+ consola: "npm:^3.4.2"
+ crossws: "npm:^0.4.12"
+ db0: "npm:^0.4.1"
+ env-runner: "npm:^0.2.1"
+ h3: "npm:^2.0.1-rc.31"
+ hookable: "npm:^6.1.1"
+ nf3: "npm:^0.3.24"
+ ocache: "npm:^0.3.0"
+ rolldown: "npm:^1.2.7"
+ rou3: "npm:^0.9.2"
+ srvx: "npm:^1.0.3"
+ unenv: "npm:^2.0.0-rc.24"
+ unstorage: "npm:^2.0.0-alpha.10"
+ bin:
+ nitro: dist/cli/index.mjs
+ checksum: 10c0/7947c389578c42333b5e8e2bf21e275c5396cb6a9e25ca87ff80c108d199a5a2aa60e08aad369d67c853f866aa4eb355b5e3ca985f17df67dad90f5449a74754
+ languageName: node
+ linkType: hard
+
"node-gyp@npm:latest":
version: 13.1.0
resolution: "node-gyp@npm:13.1.0"
@@ -2978,6 +3295,13 @@ __metadata:
languageName: node
linkType: hard
+"ocache@npm:^0.3.0":
+ version: 0.3.0
+ resolution: "ocache@npm:0.3.0"
+ checksum: 10c0/1caf0f8d24ef638dde0c4a5301376c7c1d0f44f4e7ed5430012c1983d0a1af6436b5243c3adf9c85ec0d4f33c1a2ab211351fe55337cd7308abe190557f37bbd
+ languageName: node
+ linkType: hard
+
"pathe@npm:^2.0.3":
version: 2.0.3
resolution: "pathe@npm:2.0.3"
@@ -3175,7 +3499,7 @@ __metadata:
languageName: node
linkType: hard
-"rolldown@npm:~1.2.11":
+"rolldown@npm:^1.2.7, rolldown@npm:~1.2.11":
version: 1.2.12
resolution: "rolldown@npm:1.2.12"
dependencies:
@@ -3233,6 +3557,20 @@ __metadata:
languageName: node
linkType: hard
+"rou3@npm:^0.8.1":
+ version: 0.8.1
+ resolution: "rou3@npm:0.8.1"
+ checksum: 10c0/c8728cf3c41833db0e20cbadba07b3c678b8b9fb12db1d8803f275a7a6cce02d0be9bee79367575883f65659c9c0ed1001e6527146ed27772e439e5d6c68d264
+ languageName: node
+ linkType: hard
+
+"rou3@npm:^0.9.2":
+ version: 0.9.2
+ resolution: "rou3@npm:0.9.2"
+ checksum: 10c0/4b0ab14fbd3a7c60ffee1af644f618a9e76dd218cd4fbb585b8fa3601a3f25857c2b1656a215389379a7aef1e1e1897fd55e835658e9c3a5d9683571b36b3bd6
+ languageName: node
+ linkType: hard
+
"scheduler@npm:^0.28.0":
version: 0.28.0
resolution: "scheduler@npm:0.28.0"
@@ -3281,6 +3619,31 @@ __metadata:
languageName: node
linkType: hard
+"source-map@npm:^0.7.6":
+ version: 0.7.6
+ resolution: "source-map@npm:0.7.6"
+ checksum: 10c0/59f6f05538539b274ba771d2e9e32f6c65451982510564438e048bc1352f019c6efcdc6dd07909b1968144941c14015c2c7d4369fb7c4d7d53ae769716dcc16c
+ languageName: node
+ linkType: hard
+
+"srvx@npm:^0.11.13, srvx@npm:^0.11.22":
+ version: 0.11.22
+ resolution: "srvx@npm:0.11.22"
+ bin:
+ srvx: bin/srvx.mjs
+ checksum: 10c0/aae81d7aa2d43e23fd483088533ad471ee2cd28f2065b84119635fd9feabdd4bab94fc06b8d198c205e3613b552624ccd2015c887ba9ca415d9c51dde7e6ec79
+ languageName: node
+ linkType: hard
+
+"srvx@npm:^1.0.3, srvx@npm:^1.0.5":
+ version: 1.0.5
+ resolution: "srvx@npm:1.0.5"
+ bin:
+ srvx: ./bin/srvx.mjs
+ checksum: 10c0/7ff87707840af95b399a11ab0b2fba6ded66a1d4658324913a1c95c916304056e5e618a9fc93803c1351aaf6acf4f7f3c5f55f18e82110a2ce876246d770c881
+ languageName: node
+ linkType: hard
+
"tailwind-merge@npm:^3.7.0":
version: 3.7.0
resolution: "tailwind-merge@npm:3.7.0"
@@ -3352,6 +3715,13 @@ __metadata:
languageName: node
linkType: hard
+"ufo@npm:^1.6.4":
+ version: 1.6.4
+ resolution: "ufo@npm:1.6.4"
+ checksum: 10c0/3a2b29e7e3d772fbf6893d7d23bf442981457adb2fe122828abdbda89bedcb81aafd0dcc080e41b45f9a877db00cb42cbfee9639753a19d9b9bd39b5627039cf
+ languageName: node
+ linkType: hard
+
"undici-types@npm:~8.9.0":
version: 8.9.0
resolution: "undici-types@npm:8.9.0"
@@ -3366,6 +3736,15 @@ __metadata:
languageName: node
linkType: hard
+"unenv@npm:^2.0.0-rc.24":
+ version: 2.0.0-rc.24
+ resolution: "unenv@npm:2.0.0-rc.24"
+ dependencies:
+ pathe: "npm:^2.0.3"
+ checksum: 10c0/e8556b4287fcf647f23db790eea2782cc79f182370718680e3aba4753d5fb7177abf5d6df489c8f74f7e3ad6cd554b8623cc01caf3e6f2d5548e69178adb1691
+ languageName: node
+ linkType: hard
+
"unplugin@npm:^3.3.0":
version: 3.4.0
resolution: "unplugin@npm:3.4.0"
@@ -3409,6 +3788,13 @@ __metadata:
languageName: node
linkType: hard
+"unstorage@npm:^2.0.0-alpha.10":
+ version: 2.0.0-alpha.10
+ resolution: "unstorage@npm:2.0.0-alpha.10"
+ checksum: 10c0/60473155ac6900020462f4d4192ff8a300cd510e8739f7b1905faece74fe0438b01cf00a84bcda81166cc3344838492e352998e1c48d8bc1449b1191d82ed3f7
+ languageName: node
+ linkType: hard
+
"update-browserslist-db@npm:^1.3.3":
version: 1.3.3
resolution: "update-browserslist-db@npm:1.3.3"
@@ -3469,14 +3855,14 @@ __metadata:
dependencies:
"@fontsource-variable/geist": "npm:^5.3.0"
"@fontsource-variable/geist-mono": "npm:^5.3.0"
- "@hono/node-server": "npm:^2.1.3"
- "@hono/vite-dev-server": "npm:^0.26.1"
"@remixicon/react": "npm:^4.9.0"
"@shopify/hydrogen": "npm:0.0.0-preview-116d5d7-20260730141607"
"@tailwindcss/vite": "npm:^4.3.3"
+ "@tanstack/query-core": "npm:^5.104.1"
"@tanstack/react-query": "npm:^5.104.1"
"@tanstack/react-router": "npm:^1.170.41"
- "@tanstack/router-plugin": "npm:^1.168.42"
+ "@tanstack/react-router-ssr-query": "npm:^1.167.3"
+ "@tanstack/react-start": "npm:^1.168.60"
"@types/node": "npm:^26.6.4"
"@types/react": "npm:^19.3.0"
"@types/react-dom": "npm:^19.3.0"
@@ -3485,8 +3871,10 @@ __metadata:
clsx: "npm:^2.1.1"
cmdk: "npm:^1.1.1"
framer-motion: "npm:^12.42.2"
+ graphql: "npm:^17.0.2"
hono: "npm:^4.13.12"
lucide-react: "npm:^0.562.0"
+ nitro: "npm:3.0.260903-beta"
radix-ui: "npm:^1.6.7"
react: "npm:^19.3.0"
react-dom: "npm:^19.3.0"
@@ -3555,6 +3943,18 @@ __metadata:
languageName: node
linkType: hard
+"vitefu@npm:^1.1.3":
+ version: 1.1.3
+ resolution: "vitefu@npm:1.1.3"
+ peerDependencies:
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ vite:
+ optional: true
+ checksum: 10c0/6cfcd52a17339f63f71ef08787a68850a17a9d9dd7a688e29e41067f963eb2cd5192bb65d38df87fa3a733a21e0229aaa6382201655c1599699e5d6669e3e094
+ languageName: node
+ linkType: hard
+
"webpack-virtual-modules@npm:^0.6.2":
version: 0.6.2
resolution: "webpack-virtual-modules@npm:0.6.2"
@@ -3573,6 +3973,18 @@ __metadata:
languageName: node
linkType: hard
+"xmlbuilder2@npm:^4.0.3":
+ version: 4.0.3
+ resolution: "xmlbuilder2@npm:4.0.3"
+ dependencies:
+ "@oozcitak/dom": "npm:^2.0.2"
+ "@oozcitak/infra": "npm:^2.0.2"
+ "@oozcitak/util": "npm:^10.0.0"
+ js-yaml: "npm:^4.1.1"
+ checksum: 10c0/ba257ca8a29b35d916fda190659b95d861137922fc792f760223f4a3bad07b5f18c992fb3a669d3dd6de6607eff64440cda86de083fc4648e4ec6b8f6be636a0
+ languageName: node
+ linkType: hard
+
"yallist@npm:^3.0.2":
version: 3.1.1
resolution: "yallist@npm:3.1.1"