Imported from zls233/Shopify-Template (
AGENTS.md). Install upstream withnpx skills add zls233/Shopify-Template. Copyright stays with the author.
Shopify Theme Project Instructions
Project Progress Memory
Project copies should contain a repository-level PROJECT_MEMORY.md. Read it
before starting work and update it when a task changes project state. Keep
store-specific values in the project copy; this template file contains only
placeholders.
These instructions apply to the whole Shopify template repository. The template should make new stores repeatable, auditable, and safe to work on.
Template Scope
Keep this template deliberately small. It is a starter Theme plus a few reusable checks, not a Shopify framework. Prefer a direct script over a general-purpose sync framework, Service/Repository abstraction, or platform for visual regression. Add a new abstraction only after the same problem has appeared in at least two real projects and the repeated behavior is clear.
The default reusable foundation is limited to the minimal Theme skeleton, ignored environment files, store/scope validation, a small Admin GraphQL helper, and one storefront smoke test. Resource-specific sync scripts should stay inside the real project that needs them until repetition justifies promoting them here.
Operating Rules
- Identify the target store explicitly at the start of every task. Never trust
a script default, an old
.env, or the currently selected Shopify Admin tab. - Before any mutation, print or assert the store domain, app client identity, theme ID, and publication/channel IDs. After the mutation, query the same store and verify the result.
- Work against a Draft/Development Theme by default. Do not publish a theme, replace the live theme, delete products, or delete collections without an explicit user instruction.
- Treat a successful CLI command as only one part of verification. A deploy is not proof that the remote app scopes, API resources, or storefront output are correct.
- Keep a machine-readable audit file for bulk or structural work. Include the store, identity, action, stable handle/GID, counts, errors, and verification result.
Testing Policy
- By default, do not create, run, repair, or delegate unit, integration, or end-to-end tests. Only do testing work when the user explicitly requests it; never add unit tests after implementing a feature. The existing storefront smoke test is available for opt-in use, not a mandatory step in every task.
- When testing is explicitly requested, strongly prefer end-to-end tests of complex storefront behavior on the named Draft/Development Theme over isolated unit tests. Use the smallest relevant flow during development; reserve the full end-to-end suite for the end of the task, and run it only when the user has authorized testing. Do not treat a passing browser flow as proof of Admin scopes, publication, or remote data state.
- If an isolated test is genuinely necessary and explicitly requested, write down the plausible failure modes and define its scope before implementing the feature or test. Keep that test scoped to those failure modes; do not add a unit-test suite by default.
- At the end of an authorized end-to-end run, retain a reproducible, verifiable artifact: the exact command and target store/theme, code revision, test result, and relevant trace or screenshot paths. Redact secrets and keep generated artifacts out of Git unless explicitly requested. If the run cannot complete, record the blocker rather than reporting a pass.
- Theme Check, syntax/JSON checks, Admin GraphQL readback, and targeted storefront browser inspection remain separate verification activities. Report which were performed and which tests were not run.
Authentication, Scopes, and Secrets
- For merchant-owned Products, Collections, Menus, Pages, Blogs, Articles,
Publications, Files, inventory, and Metaobjects, use one consistent Admin
GraphQL identity. The direct CLI path is
shopify store authfollowed byshopify store execute; the project's own App is also supported. App-owned$appMetafield or Metaobject schemas and entries require their owning App. - Shopify CLI is appropriate for store auth and execution, app build/deploy, theme check/dev/push, and other supported operations.
- For a full store-building project, request the broad site-building scope set
at initial app installation:
write_products,write_publications,write_online_store_navigation,write_content,write_metaobjects,write_metaobject_definitions,write_files,write_inventory, andread_locations. This covers catalog, collections, publication, navigation, pages/blogs/articles, structured content, Shopify Files, and inventory work without repeated scope changes during the build. A write scope includes its corresponding read capability, so explicit duplicateread_*declarations are not needed. Do not add customer, order, payment, or other unrelated operational scopes unless the project later requires them. Theme-only projects do not need this Admin GraphQL scope set. - This template has no
shopify.app.toml. Theme-only projects do not need an App solely to request candidate scopes. Merchant-owned resource work can use CLI store auth without scaffolding a project App. If project-owned schemas or a dedicated App identity are needed, create or link this project's own App before validating or deploying its configuration. - For a dedicated project App, keep separate records of planned scopes,
scopes declared in
shopify.app.toml, and scopes actually granted to the installed App. Validate App config withshopify app config validate --jsonbefore deploying. For CLI store auth, compare requested and actually granted scopes throughconnect:shopify. - Read
currentAppInstallation.accessScopesbefore assuming a scope is active. Localshopify.app.tomlchanges do not update an existing installation by themselves; deploy and then re-authorize/reinstall the app when required. - For the direct CLI path, run
npm run connect:shopify -- --store <store>.myshopify.combefore resource work. It checks existing authorization, requests the broad site-building scopes only if needed, then verifies the real store, App identity and scopes. Reuse the stored CLI authorization; rerun the command if it expires. For the dedicated project App path, runnpm run preflight:shopify -- --store <store>.myshopify.comwith this project'sSHOPIFY_APP_CLIENT_IDand Admin token configured locally. - Check the current app's ability to perform the planned operation, not merely
whether both the
read_*andwrite_*names appear in a local list. If the task only reads a resource, request its read scope instead of its write scope. shopify app executepermits mutations only on dev stores. For production data work under CLI store auth, useshopify store execute --store ... --query-file ... --allow-mutationsand inspect GraphQL errors, userErrors, and readback. Scopes do not grant ownership of another App's Metaobjects.- In non-interactive environments, app deployment needs an explicit approval
flag, normally
shopify app deploy --allow-updates. - If CLI app installation only supports an organization dev store, do not mistake that for access to an arbitrary store. Use the current operator's Shopify Partners account to request or approve access to the target store, then complete the normal Shopify CLI authorization flow. Use SunBrowser only when the user explicitly requests it for that task.
- Keep credentials in ignored
.env.local/.env.*files or an OS credential store. Never print, commit, screenshot, or put tokens/passwords in command URLs, Liquid, audit files, or generated reports. A storefront password may be entered through the explicitly selected browser session when required, but must not be persisted without explicit confirmation. - Keep captured reference source files in
references/when they are required to reproduce a project. Ignore only regenerable artifacts such asoutput/andreferences/output/; do not ignore the entirereferences/directory. Scripts must resolve the Shopify CLI from PATH and must not embed a Windows-specific user directory or shell command.
Shopify Data Model
Keep the resource graph as the source of truth:
Product attributes -> Automated Collection -> Shopify Menu -> Theme navigation -> Collection grid
- Products own product data and classification attributes. Normalize new tags
as lowercase
namespace:valuestrings such asgender:women,category:clothing, andsubcategory:pants. - Preserve unrelated existing tags, product types, and metafields. Classify from deterministic evidence in title, product type, vendor, description, existing tags, and metafields. Report ambiguous/unclassified products instead of silently guessing.
- Collections must be automated/rule-based. Reuse an existing collection by stable handle before creating one. Do not store product ID lists in Liquid or JavaScript.
- When a collection mixes categories (for example, men's or children's items appearing in a women's collection), inspect product tags/metafields and the automated collection's conditions first. Check collection counts and sample products that should both match and fail the rules before changing Liquid.
- Do not make title/handle substring filtering in Liquid the permanent source
of collection membership. If an explicitly authorized temporary storefront
guard is necessary, document that pagination and
products_countcan differ from the visible items, then remove the guard after correcting Shopify product classification and collection rules. - Publish required collections and products to the Online Store channel
explicitly.
ACTIVEstatus is not the same as Online Store publication; usepublishablePublish(or the equivalent API) and verify publication. - Menus own labels, hierarchy, and destinations. Update the existing menu by handle when possible; do not create duplicate menus for the same surface. Leaf items should link to real Shopify Collection resources.
- Use Metaobjects for optional structured presentation data such as mega-menu
banners, headings, descriptions, images, and featured collections. Define
app-owned schemas in
shopify.app.tomlusing$app:<type>, deploy before creating entries, and record the remote definition GID and access settings. When Liquid reads an app-owned type, use the concrete deployed type returned by Shopify (for exampleapp--<app-id>--mega_menu), not the$app:alias. Set merchant read/write access only when merchants must edit entries, and enable Storefront access only when the theme reads the type. If Shopify reports that a type is reserved or ownership is invalid, stop and record the limitation; do not retry the same mutation unchanged.
Idempotent Scripts and GraphQL
- Every mutation script must default to a dry run and require an explicit
--store. Before mutation, validate store, app identity, required scopes, and stable handles. - Use stable handles with upsert/update behavior. A rerun must not create duplicate menus, collections, pages, articles, entries, or media.
- Prefer GraphQL variables over string interpolation. Pin an explicit supported Admin API version.
- Check HTTP status, top-level GraphQL errors, and every mutation's
userErrors. Treat a partial batch as partial success and resume from an auditable checkpoint. - Retry only transient TLS/connection-reset, 429, and 5xx failures with bounded backoff. Do not retry missing scopes, ownership, schema, or validation failures unchanged.
- For large imports, show a dry-run count, batch writes, preserve a progress report, and query final counts. Network interruption does not prove that a previous batch failed; verify before repeating it.
- Use structured output, for example:
{"store":"...","action":"...","handle":"...","gid":"...","count":0,"errors":[]}.
Content Pages and Blogs
- Footer links must resolve to real Shopify Pages, Blogs, and Articles. Use a stable handle mapping and an idempotent sync script rather than fake content or hardcoded 404 fallbacks.
- Content scripts must fail safely before mutation when the installed app lacks
the ability to write content. Do not require both scope names when
write_contentalready grants read capability. A theme can retain an official external help or store-locator link as a documented fallback, but must not invent order, store, or shipping data.
Theme Architecture
- Header, mega menu, and mobile navigation must render
section.settings.menu.linksand nestedlink.links. Do not maintain a second navigation tree in Liquid or JavaScript. - Collection templates must use
collection.productswith native Shopify sorting, filters, pagination, availability, price, variants, and PDP links. Do not add a second client-side product filtering system. - Use native objects with safe fallbacks when optional Metaobject values are blank. Keep each edit in the section, snippet, asset, or template that owns the behavior.
- Variant behavior must be driven by
product.variants,variant.options,variant.featured_media, andselected_or_first_available_variant. Match bothColorandColouroption names when relevant. Never infer variants from image filenames. - A catalog made mostly of
Default Titleproducts cannot prove real option, media, price, and URL linking. Reuse an existing multi-variant product when possible; otherwise create a clearly tagged, stable-handle QA fixture only after checkingwrite_productsand publication scopes. Fixture creation must be dry-run by default, idempotent, and must verify Online Store publication. - Keep controls accessible: valid labels, keyboard operation, focus return,
aria-expanded/aria-hiddensynchronization, Escape/backdrop close paths, and mobile scroll locking.
Interaction and Motion QA
Do not implement motion from screenshots alone when the source site can be measured.
- Inventory the original site's components before editing: header/sticky states, mega menu, product cards, swatches, gallery, variants, drawers, filters, accordions, carousels, video controls, and footer.
- Use Playwright or DevTools to observe desktop and mobile default, hover,
focus, active, expanded, collapsed, and scroll states. Record trigger,
geometry,
display/visibility/opacity, transforms, z-index, overflow, pointer events, transition property, duration, delay, and easing. - Distinguish real triggers (click, hover,
aria-expanded, scroll listener, IntersectionObserver, pointer/touch) instead of converting everything to a CSS hover. - Compare the same action on the source and Draft Preview at before/mid/after states. Validate at least 1440px desktop and 390x844 mobile. Check behavior, motion, geometry, and responsive match, not just whether a click works.
- Maintain
interaction-audit.mdwith Component, Trigger, Initial/Active State, Transition, Duration, Delay, Easing, Desktop, Mobile, Evidence, Implementation, Confidence, and Validation Result. Label evidence asObserved,Source-derived, orInferred; never present an inference as a measurement. - Prefer the existing theme JS/CSS and native Web APIs. Do not copy minified analytics, tracking, account, or support scripts and do not add a large animation framework for ordinary theme interactions.
Known implementation pitfalls:
- A CSS rule such as
display:gridcan override the browser's[hidden]behavior and show every mega-menu panel. Add an explicit hidden rule with the required specificity, then test opening one panel and closing it. - A mobile drawer whose inner content is absolutely positioned can collapse to
its header height even when it has
top:0; bottom:0. Give the drawer a real viewport-sized wrapper (inset:0,min-height:100dvh) and verify backdrop,aria-hidden, andbody { overflow:hidden }all reset on close. - Do not treat Shopify
shop.appiframe/CSP, favicon, telemetry, or third-party CDN errors as Theme JavaScript failures. Separate console noise from actual theme errors in the audit.
Browser, CLI, and Local Workflow
Use this order of operations:
- Shell, repository scripts, and static inspection.
- Shopify CLI store auth/execute for merchant-owned resources, or the project App plus Admin GraphQL when it owns the target resources.
- Shopify CLI for app/theme lifecycle.
- Playwright for storefront interaction and screenshot QA.
- Computer Use only for authentication or UI-only work. Default to Shopify Partners and Shopify CLI/Admin GraphQL for store access. When browser access is genuinely required, use the available authenticated browser; use SunBrowser only when the user explicitly specifies it for the task.
Partner CLI Authentication and Deployment
- Use the current operator's authenticated Shopify Partner account for Shopify CLI theme operations. Confirm that the account has approved Partner / Collaborator access to the exact target store, including the Themes permission. Do not require Theme Access,
SHOPIFY_CLI_THEME_TOKEN, or--passwordfor interactive development. Runshopify theme list --store <store>.myshopify.com --jsonto verify actual theme access before writing. - If the CLI session is missing or expired, use the normal Shopify account login flow for the current operator, then repeat the theme list check. Never switch to a merchant owner's account or use another store's credentials. Theme permissions do not replace Admin GraphQL authorization: keep store auth and effective scopes checks for resource mutations.
- Immediately before any operation targeting the live theme, run
shopify theme list --store <store>.myshopify.com --jsonthrough the verified Partner session and identify the current live theme ID. Do not trust a theme ID saved in a README, report, environment file, or prior session. - For an explicitly authorized live file change, target that freshly resolved theme ID and use
--allow-live --nodelete; add--onlyfor every changed file when the change is narrow. Never treat these flags as permission to publish or alter unrelated live theme files. - After a live push, list themes again to confirm the target remains live. Pull changed files into an isolated temporary directory with explicit
--store,--theme, and--onlyflags, then compare their SHA-256 hashes with the local source files. Also verify the affected storefront pages on desktop and mobile. - If Theme CLI reports authentication failure, first verify the selected Shopify CLI account, target store, approved Partner / Collaborator relationship, and Themes permission; rerun
shopify theme list --store <store>.myshopify.com --json. Reauthenticate only as the authorized operator when required. Report missing permissions or unresolved authentication as blockers. Do not introduce a Theme Access token as a fallback or mistake theme authentication for Admin GraphQL scopes.
Stop a long-running theme dev watcher before patching files if it holds a
lock or blocks writes; restart it with the explicit Draft Theme after edits.
If Theme Check hangs, record the tool blockage and continue with syntax,
template JSON, Liquid, and browser checks rather than claiming a pass.
Browser sampling can fill local temporary storage. Monitor free space and clean only regenerable npm/browser caches; never remove project files or browser profiles as a shortcut.
Required Verification
For app or schema changes:
shopify app build
shopify app deploy --allow-updates
For theme changes:
shopify theme check --path theme
shopify theme dev --store <store>.myshopify.com --path theme --theme <draft-theme-id>
Also run node --check for changed JavaScript, parse changed JSON templates,
and run git diff --check.
Verify through Admin GraphQL:
- installed scopes and app identity;
- Metaobject definition GIDs, fields, and access;
- stable entry handles and references;
- collection rules, counts, and Online Store publication;
- menu handle, hierarchy, and resource destinations;
- Pages, Blogs, and Articles when content was requested.
Storefront QA must cover desktop and mobile navigation, nested menu items, Collection URLs, representative positive and negative products, sorting, filtering, pagination, variant/PDP navigation, and any changed drawer or accordion paths. State clearly whether the tested theme is Draft or live.
Git and Repository Hygiene
- Keep secrets,
.env*, caches, generated screenshots, and large source media out of commits unless the project explicitly needs a tracked asset. - Before pushing, inspect tracked file sizes and
.gitignore. A Shopify theme should not accidentally carry hundreds of megabytes of generated media. - If Git appears hung, check for stale
git status/git push/pack processes and large objects before starting more commands. Clean the stale process safely, then retry with a bounded, lower-resource pack configuration or Git LFS for intentionally large assets. Verify the remote commit hash and repository visibility after push.
Completion Report
Every Shopify task should finish with:
- store and app identity used;
- scopes and ownership model;
- created/updated stable handles and GIDs;
- files changed;
- build/deploy, Theme Check, Theme Dev, API audit, and browser QA results;
- Draft vs live theme/publication state;
- remaining manual approval, reauthorization, login, or publication steps;
- known limitations and the exact next command or action to resume safely.
