Your pages & URLs
Content, titles, meta and Open Graph tags. Images and PDFs, deduplicated. Languages and redirects preserved.
An agent skill for website migrations
Give Codex or Claude Code a website. Get a local, editable Grav 2 site with the same routes and content, a matching theme, and forms that work.
Clone once, then link it into Codex:
git clone https://github.com/w00fz/grav-skills.git ~/Projects/grav-skills mkdir -p ~/.codex/skills ln -s ~/Projects/grav-skills/skills/website-to-grav ~/.codex/skills/website-to-grav
Call it with $website-to-grav. Update with git pull.
Run these inside Claude Code:
/plugin marketplace add w00fz/grav-skills /plugin install website-to-grav@grav-skills
Update with /plugin marketplace update grav-skills.
git clone https://github.com/w00fz/grav-skills.git ~/Projects/grav-skills mkdir -p ~/.claude/skills ln -s ~/Projects/grav-skills/skills/website-to-grav ~/.claude/skills/website-to-grav
Ask Claude to convert a site to Grav. Update with git pull.
Load skills/website-to-grav/ in any agent that supports Agent Skills. Or point your agent at its SKILL.md for the workflow, scripts and references.
The repository is currently private. Installation needs GitHub read access to w00fz/grav-skills.
Start with as much as you know
Then your agent gets to work
From URL to handoff
Your agent follows 13 checkpoints. You review the important choices; scripts handle the repetitive work.
Install Grav + Admin2. Connect the API and MCP before building.
Crawl routes. Audit content, forms, trackers, fonts and languages.
Choose styling, form delivery and analytics with suggested defaults.
Create pages, import media, match the theme and wire up forms.
Check every route. Compare desktop and mobile screenshots.
Get an editable site, verification reports and a connected agent.
The result
Your content becomes a real Grav site: pages you can edit, a theme you control, and an agent that can keep working.
Content, titles, meta and Open Graph tags. Images and PDFs, deduplicated. Languages and redirects preserved.
A standalone theme from measured source styles. Header, menus, CTAs and footer editable in Admin. Tailwind or plain CSS.
Inline or popup forms that save, email or send to a webhook. Choose your CAPTCHA or keep the original embed.
Admin2, REST API and MCP connected from the start. Keep editing through Admin or your agent, with secrets stored locally.
Less busywork. More of your site.
Reusable scripts keep bulk work out of the conversation. SEO details remain part of the migration, from the first route to the final check.
Code-mode efficiency
One script call can crawl or rebuild many pages. HTML, media and extracted content stay in local files; compact reports tell your agent what to inspect next. That keeps repetitive work in code and bulk data out of the context window.
SEO comes with you
Preserve URLs, page titles, descriptions and social tags. Rebuild canonical and language links, keep source redirects, and carry existing structured data into the matching templates.
Your original description, editable in Grav. The same content at the right URL.
Route checks surface content and redirect gaps. Sitemaps and robots rules are part of the workflow; local and preview copies stay out of search with noindex.
Built for the next edit
Long pages become modules, each with its own Admin form and media. Edit a hero, reorder a section or hide a form without rebuilding the whole page.
Your live page
Your editable Grav page
Articles stay in Markdown. Shared sections are stored once; popups don't count toward the threshold. Adjust it with --modular-threshold or use --modular off.
Compare. Refine. Repeat.
A first pass gets the site running. The fidelity loop brings the design closer, with measured comparisons until you're happy with the result.
Source website
Local Grav site
From the original multilingual Webflow migration, with every form browser-tested. The first pass took about 10 minutes; visual refinement took longer. These describe that migration, not a guarantee for every site.
For the curious
The workflow is explicit, the scripts are rerunnable, and the important choices stay yours.
Each stage has a check before the next begins. Your custom fixes stay in rerunnable migration/fixups/ scripts. You decide when the visual match is close enough.
PHP's built-in server by default, Docker + Mailpit, or Valet / Herd / MAMP. Choose the folder and clients: Codex, Claude Code, Cursor or another agent. Global client config changes require your approval.
Name your theme. Choose Tailwind 4 for ongoing design work or plain CSS with tokens before detailed styling begins. DESIGN.md records the decisions.
Native Grav multilang when hreflang maps translations, or separate trees per language prefix. Titles, descriptions, Open Graph and language tags come across.
Save to user/data, send through SMTP, use a webhook or keep an embed. Choose an inline message or redirect. The message reflects what actually happens.
Grav's built-in Cap is the default: self-hosted, invisible and no keys required. Turnstile and reCAPTCHA are alternatives.
Port on production hosts only, add consent gating, retain selected tags or drop them. Local and preview traffic stays out of production analytics.
~/Sites/example-grav/ ├── grav/ │ └── user/ # pages, theme, config and media │ ├── pages/ │ │ ├── 01.home/ # modular page + individual sections │ │ └── 02.about/ │ ├── themes/ │ └── media/ ├── migration/ # crawl, audit, reports, screenshots │ └── fixups/ # your rerunnable custom changes ├── .local/ # credentials, never committed ├── bin/grav-mcp # launcher reads the key at startup └── .mcp.json # project MCP configuration
Scripts write the bulk; Admin and MCP handle later edits. The page tree is generated on disk. Later agent edits use the API with conflict checks. Shared sections are stored once, and repeated layouts can become custom page types with named Admin fields.
Only grav/user needs a Git repository, if you choose one. Accounts, submissions, credentials and caches are excluded. Local credential files use restrictive permissions; agent configurations point at the launcher rather than containing a key.
Python uses its standard library; PHP uses Grav's YAML parser. Node runs MCP and, when needed, Tailwind or Playwright. Each script has --help.
| Script | Purpose |
|---|---|
install_grav.sh | Latest Grav + Admin2, PHP and extension checks. |
bootstrap_access.sh | Admin, API key and MCP launcher. Reuses credentials unless rotation is requested. |
crawl_site.py | Sitemaps, crawl, cached HTML, redirects, languages and PDFs. |
audit_site.py | Trackers, forms, embeds, code, fonts and palette. |
extract_content.py | Sections, blocks, shared content, site navigation and layout groups. |
import_media.py | Download once, deduplicate and assign page or shared media. |
build_pages.py | Page tree, modules, frontmatter, languages, provenance and redirects. |
scaffold_theme.py | Standalone theme, source CSS and design tokens, optional Tailwind. |
build_forms.py | Form plan, Grav Form pages and CAPTCHA setup. |
capture_pages.mjs | Source and local screenshots, computed styles and section measurements. |
verify_parity.py | Route, content, media, forms, SEO and analytics checks. |
grav_config.php | Read, merge and lint YAML using Grav's parser. |
Extensions: curl ctype dom gd json mbstring openssl session simplexml xml zip. Recommended: intl yaml apcu opcache. Docker brings its own runtime.
Standard library only. No pip installation for crawling, extraction or page building.
For Grav MCP, Tailwind and Playwright. Installed as needed inside the migration project.
Install the skill. Bring a website. Make it yours in Grav.