shop-builder
Build a FULL, COMPLETE content website end-to-end on this multi-tenant content platform — from the homepage to EVERY page (about/services/contact/legal/404), custom content types + records, customizer-editable sections, a theme palette, and mobile-ready chrome with nav authored in the header/footer link_list. Also covers MCP setup (.mcp.json, wmk_ API key, scopes). Use when the user says "build me a website", "build full website", or wants a multi-step site built. This platform is CONTENT-ONLY — no products, cart, checkout, payments, or menus. ALWAYS clarify brand and pages up front.
End-to-end orchestration over the content-site MCP for a new or empty site (creates content + can seed demo records).
This platform is CONTENT-ONLY — CMS pages + custom content types/records + theme sections. There are NO products, collections, cart, checkout, payments, discounts, reviews or menus, and NO tools for them. Nav is authored in the header/footer section's
link_listblock. Readshop-core-rulesfirst — §A (confirm plan), §B (extract design spec), §C (images), §D (verify on draft), §E (links), §F (design contract), §G (palette) + §G.2 (Tailwind utility classes — PREFER them for layout/spacing/type), §H (NO-HARDCODE), §I (durability) apply throughout and are NOT repeated here. ⚠️ Redesigning a site that ALREADY has data (pages/content)? Useshop-redesign— it works on a draft, reuses the content, never wipes data or changes URLs.
This composes the focused skills:
- shop-content-site — the content platform model: the
contentLiquid Drop, theurl_patternrouter, list/detail templates, commerce-off chrome. - shop-create-content-type — custom content types + records (listings/directories: houses, dishes, projects, team, services…).
- shop-build-section — customizer-editable sections placed on pages (+ the global palette via
set_global_settings, per core §G). - shop-i18n — when the site is multi-language.
- plus pages tools (
create_page/update_page_sections/publish_page).
0. MCP setup (do once)
The tools come from the shop MCP server. It auths with an org-level wmk_ API key and talks to /graphql.
Register it (project .mcp.json, or claude mcp add):
{ "mcpServers": { "shop": {
"command": "/abs/path/backend-go/bin/shop-mcp",
"env": {
"SHOP_GRAPHQL_ENDPOINT": "http://localhost:8080/graphql",
"SHOP_API_KEY": "wmk_…",
"SHOP_STORE_SLUG": "serene-living",
"SHOP_ORG_ID": "39",
"SHOP_STORE_ID": "41"
} } } }
- Create the
wmk_key in admin → Settings → API Keys. For building, grantwebstore:write+settings:write(or Full access for a trusted local key).clear_storefront_cacheneedssettings:write. SHOP_STORE_SLUGlets the server auto-resolve store/theme id;SHOP_ORG_IDis still required for org-scoped mutations. Runget_contextto confirm what resolved.
1. Clarify the brief — ASK first (then confirm the plan per core §A)
Before building anything, confirm with the user (batched into one question set):
- What is the site? — the content-site type (agency/portfolio, real-estate listings, restaurant menu, brochure, blog, services…). This shapes which content types + pages it needs.
- Brand — name, colors, fonts (feeds the palette, core §G).
- What's listed — which custom content types (houses/dishes/projects/team/services…) the design implies. Always ASK whether the site needs a custom listing beyond plain CMS pages, and propose candidates from the design (follow shop-create-content-type §0–§1). Small fixed/secondary content = section
{% schema %}blocks; a high-volume/growing listing = a content type. - Pages & nav — which pages (home, about, services, contact, legal…) and the nav structure (authored in the header/footer
link_listblock; core §H). - Real content or demo? — get real data where possible; offer to seed a few demo records so the site isn't empty (say so explicitly).
Then present a concrete plan and WAIT for approval (core §A) before any mutation.
1.5 Extract the design spec FIRST
If the user gave a design (image/mockup/URL/brief), the build will NOT look like it unless you first turn it into a concrete measurable spec — do the core §B protocol. That spec is both your build target and the §D grading checklist; carry it through the whole build.
2. Recommended build order
get_context→ confirm org/store/theme. Also confirm the store LOCALE + CURRENCY match the intended market / sample data — a VI site should bevi_VN+ VND, an EN/US siteen_US+ USD. A site whose language doesn't match its content (English chrome on a VI build) is wrong — reconcile before building.- Global look:
set_global_settingswith the extracted hex/fonts (core §G/§B), not approximate defaults. Generic palette = generic site. - Data (source images per core §C — Pexels stock via
search_stock_imagesby default, or the store's own ingested/uploaded media; re-host everything):- Content types → shop-create-content-type (+ records) — for ANY listing the built-ins don't fit (a high-volume/growing/primary custom listing). ASK + propose from the design. Small fixed/secondary content = section
{% schema %}blocks.
- Content types → shop-create-content-type (+ records) — for ANY listing the built-ins don't fit (a high-volume/growing/primary custom listing). ASK + propose from the design. Small fixed/secondary content = section
- Sections & pages — build EVERY page in the design, not just home. Enumerate every page the design/nav implies (home, about, services, contact, listings, legal…) and build each one's CONTENT — a build that styles the homepage and leaves the rest blank is INCOMPLETE (every empty page fails §D).
- Home + bespoke landing pages → one small section PER design block (hero, features, testimonials, FAQ, CTA…), built + placed ATOMICALLY, in visual order top → bottom (
build_sectionthen immediatelyset_section_settings { position: i }for that section, THEN the next — never batch all Liquid then all JSON; core §K). This is what lets the live preview fill in region by region. NEVER bake a whole page into one monolithic section (core §K). If an approved mockup was handed to this build (the draw-first gate,shop-design-concept), itsdata-mock-regionorder IS your section order — one task item per region in that order. Header/footer stay GLOBAL chrome (restyle the existing chrome section, core §H). - Content-record surfaces are DYNAMIC — bind to the
contentDrop, never hard-code a card: a records showcase on the home (or anywhere) loops thecontentDrop ({% for r in content.<type> %}) with the record's own fields ({{ r.url }},{{ r.image }}); a listing page uses the-listtemplate'srecords. A baked card goes stale the instant the merchant edits a record = §D fail. Create the records FIRST (step 3) so these render real data instead of empty grids. - Static/marketing pages (about, services, contact…) → build them SECTION-BY-SECTION too (core §K):
create_pageFIRST (an empty/skeleton page — title + slug, nosectionsyet, or one minimal section) so the page EXISTS and the editor can open it without a 404, THENupdate_page_sections { id, section_id, type, settings, position }once per section, in visual order top → bottom. It merges per-field (settings you don't pass are preserved) and the preview follows to the page. ⚠️ Do NOT dump the whole sections document via a singlecreate_page/update_page. Prosebodyis ONLY for pure-text pages (privacy/terms/policies). ⚠️create_pagewith NEITHER sections NOR a follow-upupdate_page_sectionsmakes a BLANK page — the #1 blank-page cause. A contact/booking form = anis_formcontent type wired to the form section. Publish each withpublish_page. - Repeating listings (jobs, properties, projects, dishes…) → a content type + its
-list/detail.jsontemplates so those pages actually render (seeshop-content-site/shop-create-content-type) — creating the type + records but NOT the templates = a 404/empty listing. - ⚠️ DATA ≠ DESIGN — the content-type TEMPLATES are first-class design surfaces, not data. Creating records is the easy half; the pages that render them (the content-type list + detail templates) are designed exactly like the homepage — decompose each into real sections per core §K (list: filterable styled grid bound to
records; detail: gallery + fields laid out + CTA). The bare default templates render sparse and generic — shipping them unchanged is the #1 "listing looks half-finished" failure. Treat them as pages: design, then VERIFY (§D). Then WALK THE NAV: every nav link must resolve to a BUILT, non-empty page (§E).
- Home + bespoke landing pages → one small section PER design block (hero, features, testimonials, FAQ, CTA…), built + placed ATOMICALLY, in visual order top → bottom (
- Navigation + header/footer chrome: author the nav links in the header/footer section's nav link blocks — 'link' + nested 'dropdown'/'column' (link to pages/content-type routes — core §E real paths). Then RESTYLE THE EXISTING header/footer section to match the design —
web-header/web-footer(get_theme_file→upsert_theme_file, keep the live bindings). Do NOT bake a new homepage section with a hard-coded<nav>/<a>menu — the nav must loop thelink_listblock, the logo fromshop.logo_url(core §H "Header & footer = layout chrome" + logo rules). A hard-coded header that ignores the nav = a §D fail. - Verify VISUALLY on the draft — the mandatory gate, EVERY page, per core §D (home, content list+detail, every static page, 404, header & footer; grade attribute-by-attribute against the §B spec; exercise interactivity; walk every link per §E). Mobile per core §L is graded with the same rigor — burger menu opens AND closes every way, no overflow, grids stack. Don't publish until the full checklist passes.
- Publish & refresh:
publish_draft_theme, thenclear_storefront_cache.
2.9 FULL-SITE COMPLETENESS CHECKLIST — a website is DONE only when ALL of this holds
QA is a HARD GATE, not a cursory glance. Do NOT publish until EVERY box below passes — loop (screenshot → find a defect → fix → re-screenshot) for as many rounds as it takes. Any ✗ = incomplete, keep working:
- Homepage: every design block built as its own section, in order (§K), with REAL copy + re-hosted images (§C) — zero placeholders/lorem.
- Every nav target exists & has content: walk the header/footer nav link blocks — each link resolves 200 to a BUILT page (§E). No "coming soon", no blank page.
- Static pages (about/services/contact/policies): created with
sections(visually editable), styled to the design; contact has a working form (anis_formcontent type wired to/api/storefront/forms/submit). - Custom content types (if any): type + records + BOTH list & detail templates render (a type without templates = 404 listing).
- Dynamic, NOT hard-coded: every content-record surface (home record strips, list template, related strips) LOOPS the
contentDrop /records— ZERO hard-coded cards, values or images. Proof: editing a record in admin changes the storefront. A baked card = §D fail (core §H). - Everything created is PUBLISHED / visible (draft = invisible): content records published, pages published (
publish_page), and the draft THEME published at the end. Seeding a record but leaving it draft = it never appears = a defect. - Global chrome — the EXISTING header/footer RESTYLED, never self-written: exactly ONE global header + ONE global footer (
web-header/web-footer), restyled to the design viaget_theme_file→upsert_theme_file, appearing on EVERY page from the layout; nav loops thelink_listblock (§H), logo fromshop.logo_url, footer columns/copyright real. A NEW/custom header-footer section, two stacked headers, or a baked<nav>/<a>menu inside a page/hero section = FAIL — restyle the existing chrome. - No duplicate / colliding section types: header/footer are OVERRIDDEN (never a 2nd global header/footer). For other blocks, reuse/override an existing type if one fits; only create a NEW type with a UNIQUE handle (
hero+my-hero= collision → the storefront renders the OLD section's content). Verify each placed section renders ITS intended content. - Mobile (§L): burger menu fully functional (opens, closes by X/backdrop/link/Escape), no horizontal overflow on ANY page, grids stack, touch targets ok.
- One consistent design system: every page uses the SAME palette tokens, type scale, spacing rhythm and button/card style — no page/section looks like a different theme. Restyle any odd one out.
- No layout defects (screenshot-grade, every page): nothing overflows its container or the viewport (tràn trang); the header nav fits ONE line; grids have NO orphan/empty cells; no clipped/overlapping text, no stretched/squished images.
- Locale & language match the content: the UI/content language matches the sample data (a VI site must not show English chrome — set at store creation; fix if mismatched).
- No fake features: EVERY interactive element exercised, not eyeballed — each form SUBMITTED and a record confirmed stored (real
is_formcontent type +/api/storefront/forms/submit, never an invented endpoint), each slider/tab/accordion/drawer opens AND closes, each CTA/link reaches a real page. A control that doesn't work is removed or fixed, never shipped as a mockup. - 404 page styled; theme settings palette = the extracted spec (§G/§B), not defaults.
- SEO configured from THIS site's config:
update_store_brandingsetsmeta_title+meta_description+og_image_url+favicon_url(real brand/shop.name, a hosted OG image), plus per-pagemeta_title/meta_descriptionon home + key pages viacreate_page/updatePage. The layout already bindspage_title/page_description/OG from config (§H) — this fills it in. QA: every page has a real<title>+ meta description + OG, none hardcoded. - Long pages reviewed SECTION-BY-SECTION: for a tall page don't rely on one giant full-page shot —
screenshot_previeweach section viasection: '[data-section-id="…"]'and judge close-up, then ONE tiled full-page shot for the global overflow/rhythm pass. - §D visual verify passed for EVERY page above, desktop + mobile, then publish + cache clear.
3. Escape hatch
Anything not wrapped by a high-level tool: introspect_schema (e.g. type_name:"Mutation") then graphql_query / graphql_mutation. Org/store-scoped ops need organization_id/store_id from get_context. (The §F design contract runs inside the backend too — no bypass.)
Tool index
Content: create_content_type create_content_record list_content_types list_content_records set_commerce_enabled
Theme: build_section set_section_settings set_global_settings list_theme_files get_theme_file upsert_theme_file customize_theme publish_draft_theme create_theme_preview screenshot_preview clear_storefront_cache
Pages: list_pages create_page update_page update_page_sections publish_page delete_page
Verify/media: screenshot_preview (draft, mobile/tablet/desktop) check_links upload_image search_stock_images search_stock_videos
i18n: get_languages set_languages list_translations upsert_translations
Meta: get_context list_liquid_objects graphql_query graphql_mutation introspect_schema
