Content & layout projects
This is the project playbook for the design team: how to take a batch of SEO content (city pages, service pages, or blog posts written in Google Docs) and turn it into Elementor drafts on a WordPress site using the SEO Navigator MCP. It is the “how we actually run a client project” layer above the single-tool pages (Pages, Elementor template duplicate).
It is distilled from two real projects — Modern Collision (auto-body shop, city + service pages) and Charlotte Window Tinting (20-post blog batch). Both follow the same backbone; they differ only in how the layout is produced.
Hard rule, every project: everything ships as draft. The MCP cannot publish. The design team reviews, fixes, then a human clicks Publish in wp-admin. See Publishing & preview.
Tutorial video
Section titled “Tutorial video”Video walkthrough coming soon — placeholder reserved.
The two patterns
Section titled “The two patterns”Pick one per project (or per page type) based on whether a good layout already exists on the live site.
| Pattern | Use when | How layout is produced | Example |
|---|---|---|---|
| Clone & customize | A published page already has the layout you want | save-as-template an existing page → apply-template to a new draft → swap text fields | Modern Collision city/service pages (cloned from the Columbus page) |
| Generate from source | No reusable page exists, or you need many uniform pages | Author content as block-schema JSON → a build script emits Elementor template JSON → import-template | Charlotte Window Tinting 20-post blog batch |
Both end the same way: a draft page with the correct page template, SEO meta, and a UAT pass.
Updating an already-published page
Section titled “Updating an already-published page”Both patterns above assume you are creating a new page. The hard rule — MCP ships drafts only, never publish-now, never touch a live page — still holds. So to update a page that is already published, never edit the live page directly. Instead, make a draft copy first with the Yoast Duplicate Post plugin, edit that draft via the MCP, then republish.
Use the plugin’s Rewrite & Republish action (not plain Clone): it creates a
draft copy linked to the original, and on republish it merges the changes back
into the original post — same post_id, same URL, no duplicate page and no
lost SEO history. (Modern Collision’s homepage rewrite used exactly this:
“Rewrite & Republish draft clone” of the live home page.)
Flow:
- In wp-admin, on the published page, click Rewrite & Republish (Yoast Duplicate Post) → it opens a draft copy.
- Note that draft’s
post_idand hand it to the MCP. Now it’s a normal draft: edit text in place withupdate-element/update-widget, or apply the clone/generate patterns above. - Update SEO meta/schema on the draft (
set_seo_meta,set_seo_schema). - UAT the draft.
- A human clicks Republish in wp-admin — the edits merge back onto the original published URL.
Why not just edit the live page? Editing published content via MCP is gated behind the
allow_seo_on_publishedflag and is risky — a half-finished edit is live immediately. Rewrite & Republish keeps all work on a draft until a human approves. See Publishing & preview.
The pipeline (every project)
Section titled “The pipeline (every project)”Google Sheet (topics + SOP doc links) └─ Google Docs (per-page content, written to SOP structure) └─ Local repo (content/ source + scripts/ build + generated artifacts) └─ SEO Navigator MCP → WordPress drafts (Elementor) └─ UAT (render, schema, links, images) → fix in place └─ Human publishes in wp-admin1. Set up the project repo
Section titled “1. Set up the project repo”One git repo per client site. Keep the source of truth (content) separate from generated artifacts (Elementor JSON, batch ops), and gitignore the generated build output.
<client>/ CLAUDE.md # site facts + pipeline + gotchas (read this first) README.md # deliverables table: page → WP id → target URL content/ (or articles/source/) # canonical content, one file per page scripts/ # build/transform scripts (Node ESM) build/ (gitignored) # generated Elementor JSON + batch ops uat/ # UAT findings + fix ownershipThe CLAUDE.md in each project repo is the single most important file — it records the verified site facts (see step 2), the exact MCP call sequence, and the project-specific gotchas. Start every project by filling it in.
2. Verify and record site facts
Section titled “2. Verify and record site facts”Before building anything, confirm the site is reachable and record these in the project CLAUDE.md. See Prerequisites for the full checklist.
list_sites # confirm the token can see the siteping_site / diagnose_site # confirm the MCP adapter answerslist_builders_for_site # confirm Elementor is availableRecord:
site_id(e.g.modern-collision,charlottewindowtinting)- Page template to set on every draft — this is per-site and is not
copied by the clone/import step (see gotchas). e.g.
page-templates/fullwidth-content.phportemplate-elementor.php. - RankMath status — whether
set_seo_meta/set_seo_schemawork, or whether schema has to go in an HTML widget / be set in wp-admin.
3. Source the content
Section titled “3. Source the content”Content is written by the content team in Google Docs, linked from a Google Sheet (the “SOP Onsite SEO V2” column). Pull each doc into the repo as the canonical source.
- Keep a registry mapping each page: topic → slug → target URL → source doc →
post_id(filled in once the draft exists). Modern Collision uses theREADME.mddeliverables table; Charlotte usesarticles/_index.json. - Tip: export the Sheet as
.xlsx, not CSV/HTML — only.xlsxpreserves the hyperlink targets to each Google Doc.
Every page follows the same SOP content shape: title tag, meta description, H1 + intro (BLUF), H2 sections, comparison/spec tables, FAQ block, and a CTA with NAP. City pages add a Service-Area table and a local-geography section.
4. Produce the layout
Section titled “4. Produce the layout”Clone & customize (Modern Collision):
elementor-mcp-save-as-template(source_post)→template_id- Create the new draft, then
elementor-mcp-apply-template(new_id, template_id)— this inserts the element tree with fresh widget IDs. update_page_draft(..., template='page-templates/fullwidth-content.php')— set the page template explicitly (the apply step copies elements only).elementor-mcp-get-page-structure(new_id)to read the new widget IDs, map old → new, thenelementor-mcp-batch-updatethe text fields (title,editor,title_text,description_text, accordiontabs[], rawhtml).- Chunk batch updates to ~10 ops per call to stay within payload limits.
Generate from source (Charlotte Window Tinting):
- Author each page as block-schema JSON — an ordered
blocks[]ofh1/h2/h3/p/ul/ol/table/toc/faq. - Run the build script (
build-elementor.js) to emit Elementor template JSON deterministically (stable IDs, same input → same output). Generate a human-readable Markdown mirror too, for review. create_draft(title, slug, excerpt)→post_idelementor-mcp-import-template(post_id, json, position=-1)elementor-mcp-update-page-settings(post_id, template='template-elementor.php')elementor-mcp-get-page-structureto verify the section/widget tree rendered.
5. SEO metadata
Section titled “5. SEO metadata”On the draft (never on a published page without explicit approval), set:
set_seo_meta— title tag, meta description, focus keyword (RankMath).set_seo_schema— Article/BlogPosting + FAQPage. If the RankMath bridge is unavailable on a site, ship schema as a JSON-LD<script>inside an HTML widget instead, and record that fallback in the project CLAUDE.md.
See RankMath SEO for the field reference.
6. UAT, then publish
Section titled “6. UAT, then publish”Run a UAT pass on every draft and log findings in uat/. Categorize each issue
by owner: MCP-fixable (text, links, structure), design-judgment
(imagery, spacing, icon grids), or site-level (redirects, theme template).
Fix MCP-fixable issues in place with update-element / update-widget —
do not re-import or re-clone to fix a small thing (see gotchas). When the
draft passes, hand off; a human publishes in wp-admin.
Gotchas (learned the hard way)
Section titled “Gotchas (learned the hard way)”These cost real time on the two pilot projects — internalize them.
| Gotcha | What happens | Do this |
|---|---|---|
| Page template not copied | Clone/import brings the elements but the new page keeps the default theme layout (wrong width, header). | Always set the page template explicitly after apply/import (fullwidth-content.php, template-elementor.php, etc.). |
| Re-import reverts to fallback | Re-importing a template flips the post out of Elementor “builder” mode → renders raw fallback, and the MCP can’t flip it back. | Never re-import to make a small change. Edit in place. If a post is stuck in fallback, open it once in the Elementor editor to restore builder mode. |
| Batch payload too large | A big batch-update silently fails or errors. | Chunk to ~10 ops per call. |
| Can’t publish via MCP | There is no publish tool. | Ship drafts; a human publishes. |
| Per-page local references | City/service pages must reference the right city, routes, drive times, local law — copy-paste leaks the source city. | Drive these from the per-page content/script, not by hand-editing a clone. |
| CSV strips Doc links | Exporting the content Sheet as CSV/HTML loses the hyperlinks to each Doc. | Export .xlsx and read the hyperlink targets. |
Project checklist
Section titled “Project checklist”- Repo created;
CLAUDE.mdfilled with verified site facts + page template - Site reachable (
list_sites,ping_site,list_builders_for_site) - Registry maps every page → slug → target URL → source doc
- Pattern chosen per page type (clone vs generate)
- Drafts built; page template set on each
- SEO meta + schema set on drafts
- UAT pass logged in
uat/; issues categorized by owner - MCP-fixable issues fixed in place
- Handed off for human publish
See also
Section titled “See also”- Elementor template duplicate — the clone primitive
- Pages (Gutenberg / Elementor)
- RankMath SEO
- Content + Design teams — the role split
- Publishing & preview branches