Skip to content

08 — GitHub Design Team Flow

The designer-side of the content + design split. The designer never opens the writer’s Claude session — they only see what arrived in GitHub. Their workflow: list pending posts, pick one, deploy it as a WordPress draft, then flag the file as deployed so the same post doesn’t get deployed twice.

Designer

Show me what the content team has ready for design on viper-template.

Claude
list_md_from_github

Five posts ready for design on supportsn/seo-navigator-content:

  1. Ceramic Coating Explainedviper-template/posts/ceramic-coating-explained.md (4.9 KB)
  2. Interior Detailing: A Step-by-Step Guide From Vacuum to Leather Conditioninginterior-detailing-step-by-step.md (7.5 KB)
  3. Paint Correction Explainedpaint-correction-explained.md (7.6 KB)
  4. Paint Protection Film: A Buyer’s Guidepaint-protection-film-buyers-guide.md (5.6 KB)
  5. Window Tint: Ceramic, Carbon, and Dyed Films Comparedwindow-tint-types-explained.md (6.3 KB)

All status draft per their frontmatter. Want me to deploy one to WordPress?

Designer

Yes — deploy the ceramic coating post as a WP draft on viper-template. Then mark the markdown file as deployed.

Claude
deploy_md_to_site update_md_status

Done — the post is sitting in WordPress as a draft.

  • WP post ID: 41
  • Status: draft
  • Preview: https://viper-template.on-forge.com/?p=41 (theme preview; will 404 for non-logged-in visitors until published)
  • wp-admin: https://viper-template.on-forge.com/wp-admin/post.php?post=41&action=edit

The MD file frontmatter is updated:

  • statusdeployed
  • deployments → appended with { site_id: viper-template, post_id: 41, deployed_at: 2026-05-26T... }

Next list will hide this one because it’s no longer status: ready-for-design. The content team can see your hand-off in the file’s git history.

The deploy_md_to_site tool does three things in one call:

  1. Reads the MD from the source repo via the GitHub App installation token
  2. Parses frontmatter and dispatches by type (default post → calls create_draft under the hood; page → calls create_page_draft)
  3. Resolves taxonomy strings to IDs: WordPress REST requires integer IDs for tags and categories, so any string names in the frontmatter (tags: [ceramic-coating, ...]) get looked up (or created if missing) and replaced before the WP POST

The whole flow is drafts only — the worker has no publish_post tool, so even if the designer asks Claude to “publish it now”, the post will sit as a draft until someone clicks Publish in wp-admin.

GitHub commits page shows both the original push (writer) and the deploy metadata update (designer):

GitHub content repo

Audit log shows both deploy_md_to_site and update_md_status calls with the designer’s user_id:

Audit log with deploy and update_md_status entries

If deploy_md_to_site fails with E_BUILDER_REQUIRED, that means the target site has more than one page builder enabled (Gutenberg + Elementor) AND the MD has type: page. The designer needs to pass page_builder=gutenberg explicitly — see Multi-builder dispatch.

Demonstrate the design-team half of the editorial workflow: pick a markdown file out of the GitHub repo, render it into the target CMS as a draft, and update the frontmatter status so the file stops appearing in the queue.

  • Scenario 07 has been completed at least once; at least one markdown file in the content repo has status: ready-for-design and a valid target_site.
  • The connector is connected (scenario 01).
  • The target site in the frontmatter is reachable (scenario 05 passes).
  • Claude Desktop on a new conversation.
  • A WP admin tab open on …/wp-admin/edit.php?post_status=draft&post_type=post for the target site so you can verify the new draft appears.
  1. Action: In the composer, type:

    List all markdown files in acme-org/blog-content with status ready-for-design and show the slug, target_site, author.

    Press Enter. Expected: Claude calls list_md_from_github with a status filter and returns a markdown table. Recorder: pause two seconds on the table so viewers can read the row from scenario 07.

  2. Action: Type:

    Read the file for slug cut-lcp-nextjs so I can review the body.

    Expected: Claude calls read_md_from_github, returns frontmatter + body. Body renders as markdown in chat. Recorder: scroll the body once.

  3. Action: Type:

    Looks good. Deploy it to the target site listed in the frontmatter as a WP draft. After it deploys, set the GitHub file’s status to deployed.

    Expected: Claude does three calls in sequence:

    1. deploy_md_to_site — passes the parsed frontmatter + body to create_draft on target_site=acme-blog, returns { post_id, edit_url }.
    2. update_md_status — patches the frontmatter to status: deployed, adds deployed_post_id and deployed_at.
    3. Claude summarises the result. Recorder: capture all three tool cards in order; the chained nature is the point of the scenario.
  4. Action: Switch to the WP admin draft list and refresh. Expected: A new draft titled “How we cut LCP by 40% on a Next.js blog” appears, status Draft. Recorder: highlight the new row.

  5. Action: Switch to GitHub and refresh the file. Expected: The frontmatter now shows status: deployed, deployed_post_id: <n>, deployed_at: <ISO timestamp>. Recorder: highlight the changed lines in the diff view (?diff=split).

  6. Action: Back in Claude Desktop, type:

    List ready-for-design files again.

    Expected: The file is no longer in the list. Recorder: a satisfying empty/short table.

  • WP admin shows the new draft with the correct title and body (markdown converted to Gutenberg blocks).
  • GitHub file frontmatter is updated.
  • MCP Audit log has three new rows: list_md_from_github, read_md_from_github, deploy_md_to_site, update_md_status — all ok.
  • Trash the WP draft post.
  • In GitHub, set the file’s status back to ready-for-design (or delete the file) if you plan to re-run the demo.
  • target_site missing from frontmatter: deploy_md_to_site returns E_TARGET_SITE_MISSING. Show Claude asking the user which site to use, then resubmitting with the override.
  • target_site does not exist in the user’s scope: E_SITE_NOT_FOUND. Show Claude listing valid sites and asking which to pick.
  • Frontmatter has unknown keys: deploy succeeds, but the unknown keys are preserved in the GitHub file (not copied to WP). Show this trade-off if your recording has time.