From website-creator
Imports existing website content from WordPress XML exports or by scraping sites for redesigns. Parses posts, pages, categories, tags, menus, and metadata.
npx claudepluginhub burtrw/website-creator --plugin website-creatorThis skill uses the workspace's default tool permissions.
Import existing content when redesigning a site.
Exports WordPress pages, posts, custom posts to portable local packages with builder data, media, markdown previews. Imports with smart ID remapping. Auto-backups before AI edits.
Installs relevant WP.org plugins, generates AI placeholder content (pages, posts, menus), creates images, and re-exports database for WordPress NL site builds after theme activation.
Extracts content from closed platforms (GoDaddy, Hostinger, HubSpot, Shopify, Squarespace, Webflow, Wix) into WordPress WXR files. Exports products to WooCommerce CSV; supports discovery, verification, resume, and import.
Share bugs, ideas, or general feedback.
Import existing content when redesigning a site.
The most complete option — includes posts, pages, categories, tags, menus, and metadata.
How to get it: Tools → Export in WordPress admin (or Settings → Export on WordPress.com)
import xml.etree.ElementTree as ET
from html import unescape
def parse_wordpress_xml(xml_path):
"""Parse WordPress XML export file."""
tree = ET.parse(xml_path)
root = tree.getroot()
ns = {
'wp': 'http://wordpress.org/export/1.2/',
'content': 'http://purl.org/rss/1.0/modules/content/',
'excerpt': 'http://wordpress.org/export/1.2/excerpt/',
}
content = {
'site_title': '',
'site_description': '',
'posts': [],
'pages': [],
'categories': [],
'tags': [],
'menus': [],
}
channel = root.find('channel')
content['site_title'] = channel.findtext('title', '')
content['site_description'] = channel.findtext('description', '')
for item in channel.findall('item'):
post_type = item.findtext('wp:post_type', '', ns)
status = item.findtext('wp:status', '', ns)
if status != 'publish':
continue
entry = {
'title': item.findtext('title', ''),
'slug': item.findtext('wp:post_name', '', ns),
'date': item.findtext('wp:post_date', '', ns),
'content': unescape(item.findtext('content:encoded', '', ns) or ''),
'excerpt': unescape(item.findtext('excerpt:encoded', '', ns) or ''),
}
if post_type == 'post':
entry['categories'] = [c.text for c in item.findall('category[@domain="category"]')]
entry['tags'] = [t.text for t in item.findall('category[@domain="post_tag"]')]
content['posts'].append(entry)
elif post_type == 'page':
content['pages'].append(entry)
elif post_type == 'nav_menu_item':
content['menus'].append({
'title': entry['title'],
'url': item.findtext('wp:postmeta[wp:meta_key="menu_item_url"]/wp:meta_value', '', ns),
})
for cat in channel.findall('wp:category', ns):
content['categories'].append({
'name': cat.findtext('wp:cat_name', '', ns),
'slug': cat.findtext('wp:category_nicename', '', ns),
})
return content
If user doesn't have an export file but provides their site URL, scrape key pages:
def scrape_existing_site(base_url):
"""Scrape starter content from an existing site."""
from urllib.request import urlopen
from html.parser import HTMLParser
import re
content = {
'site_title': '',
'site_description': '',
'pages': [],
'navigation': [],
}
# Pages to attempt scraping
key_pages = [
('/', 'Home'),
('/about', 'About'),
('/about-us', 'About'),
('/services', 'Services'),
('/contact', 'Contact'),
('/contact-us', 'Contact'),
]
for path, default_title in key_pages:
try:
url = base_url.rstrip('/') + path
# Use WebFetch tool to get page content
# Extract: title, main heading, body text, images
page_content = fetch_and_parse(url)
if page_content:
content['pages'].append({
'title': page_content.get('title', default_title),
'slug': path.strip('/') or 'home',
'content': page_content.get('main_content', ''),
'headings': page_content.get('headings', []),
})
except:
continue
# Try to extract navigation structure from homepage
try:
nav = extract_navigation(base_url)
content['navigation'] = nav
except:
pass
return content
What to extract when scraping:
<title> and meta description)<nav> elements)Support other formats when provided:
Ask user:
## Content Found
**Site:** [Site Title]
**Tagline:** [Description]
| Type | Count |
|------|-------|
| Pages | X |
| Posts | X |
| Menu Items | X |
### Pages
- Home — [brief description of content]
- About — [brief description]
- Services — [brief description]
- Contact — [brief description]
### Navigation Structure
- Home
- About
- Services
- Service A
- Service B
- Contact
DO NOT add content to the blueprint — it bloats the file size.
Instead, use imported content to:
The Playground preview shows the theme structure with placeholder content. The user imports their real content after deploying to their live site.
design-mockups skill informed by actual content structurewp-block-themes skill to build theme with dynamic templatestheme-deploy skill — user imports content separately on live site