Takazudo Modular Docs

Type to search...

to open search from anywhere

l-takazudo-product-on-sale

Transition a Takazudo Modular product from `mercariStatus: 'incoming'` to live on-sale state. Creates the Mercari listing draft, prompts for the new mercariProductId, removes the `mercariStatus: 'inco...

Takazudo Product On Sale (Stage 2: incoming → on-sale)

Flip a Takazudo Modular product from Coming-Soon (mercariStatus: 'incoming') to live on-sale state once the Mercari Shop listing is ready. This skill is the Stage 2 partner of /l-add-takazudo-product (Stage 1). Together they implement the incoming → on-sale two-stage release pattern that lets the product page go live before the Mercari listing exists.

This skill orchestrates existing skills (/l-add-mercari-item, optionally /l-sync-mercari-ids). It does not duplicate their content — read the linked skills when you reach each step.

When to use / when not to use

  • Use when an existing Takazudo Modular product is currently mercariStatus: 'incoming' and the Mercari Shop listing data (description, photos, price) is ready to be drafted and posted.
  • Do not use for products that are not in incoming state — this is a state machine, not a generic editor. See the pre-flight checks below.
  • Do not use for non-Takazudo brands (e.g., ADDAC, OXI Instruments, Make Noise). Mercari listings for those brands follow a different workflow handled outside this skill.
  • Do not use for adding a brand-new product. Use /l-add-takazudo-product (Stage 1) for that.

Pre-flight checks

Before doing anything, verify all of the following. If any check fails, refuse to proceed and print a clear message explaining which check failed and what the user should do instead.

  1. Slug provided — the product slug must be passed as the argument (e.g., /l-takazudo-product-on-sale zudo-3u-to-1u). If missing, ask the user once for the slug.

  2. Master-data entry existssrc/data/product-master-data.mjs contains an entry whose slug matches. If not, refuse with: “No product with slug <slug> found in master data. Use /l-add-takazudo-product first to create it.”

  3. Status is 'incoming' — that entry has mercariStatus: 'incoming'. If absent or any other value, refuse with: “Product <slug> is not in incoming state — this skill only flips incoming → on-sale. Wrong workflow.”

  4. Detail MDX existssrc/mdx/products/<slug>-intro.mdx exists. If missing, refuse with: “Product detail MDX src/mdx/products/<slug>-intro.mdx is missing — Stage 1 was incomplete. Run /l-add-takazudo-product to finish it before listing on Mercari.”

  5. mercari.png existsstatic/images/p/<slug>/mercari.png exists locally. If missing, refuse with: “mercari.png for <slug> is missing. Run pnpm r2:download (to fetch from R2) or pnpm convimgs:upload (to regenerate from /imgs/) before listing.”

  6. Every referenced image slug is registered in metadata-db.json — gather every image slug the product references and confirm each one exists as a key in metadata-db.json. The regression this catches: convimgs ran, the WebP/blurhash/mercari.png files were uploaded to R2, but metadata-db.json was never regenerated/committed. Local files look fine, R2 looks fine, but the deployed site renders a black-square blurhash placeholder on cards and an empty <ImgsGrid> on the detail page because the build-time DB lookup returns nothing. Pre-flight check 5 alone does not catch this — it only inspects mercari.png.

    How to gather slugs:

    • From the product detail MDX (src/mdx/products/<slug>-intro.mdx):
      • imgThumb, heroImgUrl, imgOgp from frontmatter (any that are present)
      • Every entry inside every <ImgsGrid srcs={[...]}> block
    • From master data (src/data/product-master-data.mjs):
      • The imgSrc of the matching entry, with the leading /images/p/ prefix stripped
    • For multi-variant products, repeat the master-data step for every variant entry that points to this detail page

    How to verify:

    node -e '
      const fs = require("fs");
      const db = JSON.parse(fs.readFileSync("metadata-db.json", "utf8"));
      const slugs = ["zudo-3u-to-1u-view1__og", "zudo-3u-to-1u-view2" /* ... */];
      const missing = slugs.filter((s) => !(s in db));
      if (missing.length) {
        console.error("Missing from metadata-db.json:", missing);
        process.exit(1);
      }
      console.log("OK — all", slugs.length, "slugs registered");
    '

    If any slug is missing, refuse with: “Image slug(s) <list> referenced in src/mdx/products/<slug>-intro.mdx (or master data imgSrc) are not registered in metadata-db.json. The convimgs/upload pipeline likely ran, but pnpm build:metadata was skipped or the regenerated metadata-db.json was not committed. Run /l-metadata-update to regenerate and ship it via the skip-CI metadata branch, then retry. Do not bypass this check — shipping the on-sale flip without it produces a live page with a black-square blurhash placeholder and an empty <ImgsGrid>.”

Step-by-step procedure

Step 1 — Generate the Mercari draft

Invoke /l-add-mercari-item and pass the slug. That skill reads the product detail MDX, transforms the content into Mercari’s format, verifies images, and appends a draft entry to sub-packages/mercari-viewer/draft.json.

Do not duplicate that skill’s content here — read its SKILL.md when you reach this step.

Step 2 — Open the Mercari viewer

Start the viewer so the user can review and finalize the draft, then post it on the Mercari Shop website/app:

pnpm mercari:dev

Then visit http://zmercari.localhost:23234 and navigate to the Drafts page. As an alternative, the user can launch the desktop wrapper tauri-mercari-viewer (also serves on the same port).

Step 3 — Wait for user confirmation

The Mercari listing must be created manually by the user on Mercari Shop’s site/app — this skill does not (and cannot) automate Mercari posting. Pause and wait for explicit confirmation that the listing is live before proceeding to Step 4. Do not assume; ask.

Step 4 — Prompt for mercariProductId

Once the user confirms the Mercari listing is posted, ask for the new product ID. Validate the input:

  • Must be a non-empty string
  • Must look like a Mercari product ID — alphanumeric, roughly 22 characters

If the input fails validation, ask again rather than guessing.

Step 5 — Edit master data

Open src/data/product-master-data.mjs, locate the entry for the slug, and apply two edits using the Edit tool (do not rewrite the file):

  1. Set mercariProductId: '<the-id>' — replace the empty mercariProductId: '' from Stage 1 with the new ID.
  2. Delete the mercariStatus: 'incoming' line entirely.

⚠️ DELETE THE LINE — DO NOT SET null OR 'available'. ⚠️

The master-data convention is clean removal: when a product is live on-sale, the mercariStatus field is absent, not null, not 'available', not any other sentinel. This keeps git diffs minimal and matches every other on-sale product in the file. Setting null or any string value is wrong for this transition — remove the whole line.

Right vs. wrong — concrete examples

Right — line removed entirely; only mercariProductId is set:

   slug: 'zudo-3u-to-1u',
   ...
-  mercariProductId: '',
-  mercariStatus: 'incoming',
+  mercariProductId: 'm12345abcdef67890ghijk',
   spec: { width: '26HP' },

Wrong — leaves mercariStatus behind in any form:

-  mercariStatus: 'incoming',
+  mercariStatus: null,           // WRONG — set to null
+  mercariStatus: 'available',    // WRONG — invented value (not in MercariStatus type)
+  mercariStatus: '',             // WRONG — empty string

Only the ✅ pattern is correct. Anything else fails the contract.

After editing, sanity-check that the file is still valid JavaScript:

node --input-type=module -e "import('./src/data/product-master-data.mjs').then(() => console.log('OK'))"

Step 6 — Optional: sync Mercari IDs from CSV

If the user just downloaded a fresh Mercari Shops CSV, also run /l-sync-mercari-ids to backfill any other products whose mercariProductId is still empty. This is optional and only worth doing when the CSV is fresh; skip if the user has nothing to sync.

Verification

Before reporting Stage 2 complete:

pnpm check          # typecheck + lint + format + MDX validation
pnpm dev            # smoke test (zmod.localhost:34434)

Manually confirm in the dev server:

  • /products/<slug>-intro/ now renders <AvailableItem> (Buy on Mercari button) — not <IncomingItem> (Coming-Soon badge + notify-me dialog).
  • View-source shows JSON-LD with "availability": "https://schema.org/InStock" (not PreOrder).
  • /brands/takazudo/ no longer shows the incoming badge on the product card.

Commit

Recommended commit message (matches the repo’s [data] scope convention):

[data] <slug>: incoming → on sale

The commit should contain only the master-data edit (and, if Step 6 ran, the additional mercariProductId backfills).

Notes

  • Removing the line, not setting null, keeps git diffs clean and matches the convention used by every other on-sale Takazudo product in product-master-data.mjs. Re-stating because this is the most common mistake on this skill.
  • Refuse on non-incoming products — pre-flight check 3 is mandatory. This skill is a state machine: incoming → on-sale, nothing else. Never silently re-write a product that is already on-sale, sold, or discontinued.
  • For non-Takazudo brands, this skill does not apply. Mercari listings for ADDAC, OXI, Make Noise, etc. follow a different (non-two-stage) workflow.
  • Manual Mercari posting — this skill stops at draft generation and waits for the user. It does not call Mercari APIs.
  • /l-add-takazudo-product — Stage 1 partner skill. Creates the product with mercariStatus: 'incoming'. This Stage 2 skill closes the loop.
  • /l-add-mercari-item — invoked in Step 1 to generate the draft entry in sub-packages/mercari-viewer/draft.json.
  • /l-sync-mercari-ids — optional Step 6 helper for backfilling IDs from a freshly downloaded Mercari Shops CSV.