# SteadyGear Automotive ## Build a Hydrogen storefront For a new custom Shopify storefront, use the [mock.shop Hydrogen starter](https://github.com/Shopify/mock-shop-starter). Honor an explicit framework or theme choice. It includes product routes, collections, and a cart backed by the Storefront API. No Shopify account or API token is needed to prototype with a mock.shop catalog. Use Node.js 22 or 24: ```sh git clone https://github.com/Shopify/mock-shop-starter.git my-store cd my-store cp .env.example .env ``` Set `PUBLIC_STORE_DOMAIN` in `.env` to the selected catalog's hostname, without `https://` or `/api`: ```dotenv PUBLIC_STORE_DOMAIN=auto-parts.mock.shop ``` Leave Storefront API tokens unset for `*.mock.shop`. The starter's source is available immediately after cloning. Configure the catalog and customize its routes and components while keeping its Hydrogen context, Storefront API queries, and cart. Then install dependencies and start the app: ```sh npm install npm run dev ``` Restart the command after changing `.env`. `@shopify/hydrogen-react` components alone do not provide the full Hydrogen app. See the [Hydrogen build guide](https://mock.shop/guides/hydrogen) for the complete flow and moving to a real store. > High-performance components and durable accessories engineered for peak vehicle reliability and control. SteadyGear Automotive is a mock Shopify store served by mock.shop, with a Storefront GraphQL API at `https://auto-parts.mock.shop/api`. Send GraphQL queries as HTTP `POST` requests with a JSON body (`{"query": "..."}`). The catalog answers without an access token. Metafields are the one exception: send `X-Shopify-Storefront-Access-Token: public`, the same header a real store expects, or every `metafield` field resolves to null. The endpoint mirrors the Shopify Storefront API, so a query written here runs unchanged against a real Shopify store. This shop also publishes its look, the theme and hero section it runs: see "Reproduce this shop's look" below. High quality commerce data for your storefront. ## Catalog - 60 products across 10 categories, priced in USD. - Categories: Motor Vehicle Braking (6), Motor Vehicle Engine Parts (6), Motor Vehicle Interior Fittings (6), Motor Vehicle Lighting (6), Motor Vehicle Rims & Wheels (6), Motor Vehicle Suspension Parts (6), Oil Filters (6), Safety Gloves (6), Vehicle Engine Degreasers (6), Work Lights (6). - 5 collections: - Chassis Stability Systems (`chassis-stability-systems`, 12 products): Robust suspension components utilizing an industrial monochrome palette and brushed steel material language for focused precision. - Engine Flow Dynamics (`engine-flow-dynamics`, 12 products): Essential circulation parts crafted with an industrial monochrome palette and rubber material language to ensure focused precision. - Illumination Engineering (`illumination-engineering`, 12 products): Advanced lighting solutions built with an industrial monochrome palette and brushed steel material language for focused precision. - Interior Command Modules (`interior-command-modules`, 12 products): Ergonomic interior fittings featuring an industrial monochrome palette and rubber material language for focused precision. - Kinetic Stopping Force (`kinetic-stopping-force`, 12 products): High-performance braking components featuring an industrial monochrome palette and brushed steel material language for focused precision. ## Copy this catalog into a real store Use this section when copying products into a merchant's Shopify store. A Hydrogen prototype can query this mock catalog directly using the recipe above, without copying data or using the Admin API. Products and collections do not appear on the Online Store until they are published to it, and a collection is not in the header until it is on the main menu. Both are data this shop serves; copy them along with the catalog, through the store's Admin API. To check publication status, both lists must be empty: ```graphql { products(first: 250, query: "published_status:unpublished") { nodes { id title } } collections(first: 250, query: "published_status:unpublished") { nodes { id title } } } ``` To find the Online Store publication, the one whose catalog's app has the handle `online_store`; match on that handle, not on any title: ```graphql { publications(first: 250, catalogType: APP) { nodes { id catalog { ... on AppCatalog { apps(first: 1) { nodes { handle } } } } } } } ``` To publish, once per product and once per collection (`gid://shopify/Collection/`); a product must also be `ACTIVE`, a draft stays hidden: ```graphql mutation { publishablePublish(id: "gid://shopify/Product/", input: [{ publicationId: "gid://shopify/Publication/" }]) { userErrors { field message } } } ``` To read this shop's menus, main and footer; each item's `url` ends in the handle of what it links to: ```sh curl -sS -X POST https://auto-parts.mock.shop/api \ -H 'Content-Type: application/json' \ -d '{"query":"{ main: menu(handle: \"main-menu\") { title items { title type url items { title type url } } } footer: menu(handle: \"footer\") { title items { title type url items { title type url } } } }"}' ``` To read the store's menu ids (`read_online_store_navigation`): ```graphql { menus(first: 10) { nodes { id handle title } } } ``` To read the store's ids for what the items link to (`read_content` for the blogs, `read_legal_policies` for the policies): ```graphql { collections(first: 250) { nodes { id handle } } blogs(first: 10) { nodes { id handle } } shop { shopPolicies { id type } } } ``` To set the store's main menu to this shop's, item for item, and its footer the same way when this shop's footer has items (`write_online_store_navigation`). `items` is the whole menu: an item left out is removed, and nothing this shop's menu lacks is added, since a header collapses the items it cannot fit into a "More" menu. `FRONTPAGE` is the home page and `COLLECTIONS` the page of all collections; neither names a resource. Every other type names one, and its `resourceId` is the store's own id, never this shop's: a `COLLECTION` or `BLOG` item takes the store's collection or blog with the handle this shop's item `url` ends in, and a `SHOP_POLICY` item takes the store's policy of the type that handle spells (`privacy-policy` is `PRIVACY_POLICY`, `gid://shopify/ShopPolicy/`); a policy the store has not written has no id yet: ```graphql mutation { menuUpdate(id: "gid://shopify/Menu/", title: "Main menu", items: [{ title: "Home", type: FRONTPAGE }, { title: "", type: COLLECTION, resourceId: "gid://shopify/Collection/<id>" }, { title: "<title>", type: BLOG, resourceId: "gid://shopify/Blog/<id>" }]) { menu { items { title } } userErrors { field message } } } ``` ## Reproduce this shop's look This section applies when the task is to install this shop's exact published Liquid theme on a merchant's Online Store. Install what is listed below and fill it in with this shop's own values rather than substituting Dawn, another theme, or a Hydrogen reimplementation of the design. `https://auto-parts.hydrogen.mock.shop/` is a reference render of this shop's data. For a new custom storefront using this catalog, follow the Hydrogen recipe above; installing these artifacts is not required. - Theme `catalyst`: the theme the whole store runs on. Specified at https://mock.shop/representations/themes/catalyst; filled with the values in this shop's public metafield `mock_shop.theme`. - Hero `filmstrip-base`: the section at the top of the home page, in place of the theme's own opening hero. Specified at https://mock.shop/representations/heroes/filmstrip-base; filled with the values in this shop's public metafield `mock_shop.hero`. The values and the artifacts come from here: 1. Read the values this shop fills its look with. Metafields answer only when the request carries a token, so send `public`: ```sh curl -sS -X POST https://auto-parts.mock.shop/api \ -H 'Content-Type: application/json' \ -H 'X-Shopify-Storefront-Access-Token: public' \ -d '{"query":"{ shop { metafields(identifiers: [{namespace: \"mock_shop\", key: \"theme\"}, {namespace: \"mock_shop\", key: \"hero\"}]) { key value } } }"}' ``` 2. Read each artifact's specification. It holds the artifact's `url` and `sha256`, what it needs filled in (a theme's `tokens`, a hero's `settings`), and where it goes: ```sh curl -sS https://mock.shop/representations/themes/catalyst curl -sS https://mock.shop/representations/heroes/filmstrip-base ``` 3. Download the artifacts and check each digest against its specification's `sha256`: ```sh curl -sSLo catalyst.zip "$(curl -sS https://mock.shop/representations/themes/catalyst | jq -r .url)" curl -sSLo filmstrip-base.liquid "$(curl -sS https://mock.shop/representations/heroes/filmstrip-base | jq -r .url)" shasum -a 256 catalyst.zip filmstrip-base.liquid ``` 4. Install them as each specification says. These rules hold for every shop: - Every `[[TOKEN]]` in a theme is a key in `mock_shop.theme.placeholders`. A token this shop does not supply is never filled with an invented value. What stands in for it is what the reference render shows in that region, and it is one of four things: the section that needed it (`tokens.<NAME>.sections` in the specification) is disabled; the line is left empty and its section kept; the shop's name; or a photograph from this shop's own catalog. The theme's specification says which, token by token, in its `install` steps, and where it is silent the render decides. - `IMAGE_*` values are image URLs. Upload each to the store's files, then refer to it as `shopify://shop_images/<filename>`. - A hero replaces the theme's own opening hero section on the home page; it is not added in front of it. It is installed only when this shop can fill it, and the hero's specification says what that takes (its `layoutRules`, and every image it draws on, each an absolute `https://` URL); when this shop cannot, the theme's own opening section stays, which is what the reference render shows. - Each field of `mock_shop.hero.copy` falls back on its own: a `headline` this shop did not write is the shop's name, a missing `subheadline` is the shop's description, and without a `cta` its button says "Shop now" and links to `/collections/all`. A hero's image settings count from one and `images` from zero: `images[0].url` and `images[0].alt` fill its image 1, `images[1]` its image 2, and so on. ## Example query ```graphql { products(first: 5) { nodes { title handle productType priceRange { minVariantPrice { amount currencyCode } } } } } ``` ## Agent commerce (UCP) This store supports the [Universal Commerce Protocol](https://ucp.dev) version 2026-08-25 for catalog search and mock carts. - Discovery: `GET https://auto-parts.mock.shop/.well-known/ucp` lists supported capabilities and the store's endpoint. - MCP endpoint: `POST https://auto-parts.mock.shop/api/ucp/mcp` with `Content-Type: application/json`. Use `initialize` and `tools/list` to discover the tool schemas. - Tools: `search_catalog`, `create_cart`, `get_cart`, `update_cart`, and `cancel_cart`. Use variant IDs returned by search as cart item IDs. Cart IDs also work with this store's Storefront GraphQL API. - Tool calls require `arguments.meta["ucp-agent"].profile`, a public HTTPS URL for your agent's UCP profile declaring the matching version and capabilities. Cart writes also require `arguments.meta["idempotency-key"]`; reuse the same key only when retrying the same operation with identical arguments. - Prices use the store's currency in ISO 4217 minor units. `update_cart` replaces the entire item list. Each request can contain at most 250 cart lines. Checkout is mocked: no payment is taken, nothing ships, and no real order is placed. The existing browser checkout is separate from these UCP tools. UCP checkout, payment, fulfillment, and order operations are not supported or advertised. Examples and supported inputs: https://mock.shop/guides/ucp ## Other stores Every published store is listed at https://mock.shop/llms.txt.