One URL.
Hello, Grav.

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.

Add it to your agent

Agent Skills format

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.

The repository is currently private. Installation needs GitHub read access to w00fz/grav-skills.

Example session

Start with as much as you know

You

$website-to-grav Convert https://example.com to Grav.

Codex

I’ll map the routes, content and design, then rebuild them in Grav. Let’s settle the choices that matter.

How would you like to style the theme?

Tailwind 4 · recommendedPlain CSS + tokens

Then your agent gets to work

Same routes
Editable site
MCP connected
Bring your site fromWebflowWordPressSquarespaceWixFramerHand-built HTML

From URL to handoff

One skill. A clear path.

Your agent follows 13 checkpoints. You review the important choices; scripts handle the repetitive work.

  1. 01 / CONNECT

    Set up

    Install Grav + Admin2. Connect the API and MCP before building.

  2. 02 / EXPLORE

    Discover

    Crawl routes. Audit content, forms, trackers, fonts and languages.

  3. 03 / YOU CHOOSE

    Decide

    Choose styling, form delivery and analytics with suggested defaults.

  4. 04 / MAKE IT REAL

    Rebuild

    Create pages, import media, match the theme and wire up forms.

  5. 05 / REFINE

    Compare

    Check every route. Compare desktop and mobile screenshots.

  6. 06 / KEEP CREATING

    Hand over

    Get an editable site, verification reports and a connected agent.

Explore all 13 checkpoints

The result

Familiar on the outside.
Editable on the inside.

Your content becomes a real Grav site: pages you can edit, a theme you control, and an agent that can keep working.

Your pages & URLs

Content, titles, meta and Open Graph tags. Images and PDFs, deduplicated. Languages and redirects preserved.

Your look & feel

A standalone theme from measured source styles. Header, menus, CTAs and footer editable in Admin. Tailwind or plain CSS.

Forms with a destination

Inline or popup forms that save, email or send to a webhook. Choose your CAPTCHA or keep the original embed.

An agent with the keys

Admin2, REST API and MCP connected from the start. Keep editing through Admin or your agent, with secrets stored locally.

Code-mode friendly scriptsSEO metadata & redirectsProduction-only analyticsNoindex for local & previewNative multilang or language treesPHP server or DockerDesign decisions in DESIGN.md

Less busywork. More of your site.

Built for agents.
Ready for the web.

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

Let code do the heavy lifting.

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.

AgentPlan & decide
ScriptsRun bulk work
ArtifactsFiles & reports
crawl_site.py → routes.json
build_pages.py → Grav pages
verify_parity.py → parity-report.md
Explore the scripts

SEO comes with you

Keep the details that help people find 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.

example.com › your-pageYour page title, preserved

Your original description, editable in Grav. The same content at the right URL.

  • URLs & 301s
  • Titles & social tags
  • Canonical & hreflang

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

A page becomes building blocks.

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

Home / modules Admin ready
01 / HeroHeading, image, call to action
02 / CardsFeatures and content grids
03 / GalleryLogos and image collections
04 / ContactFields, delivery and success
Illustrated content mapping. Hero, cards, gallery, form, shared and general section modules each have their own template and Admin form.
≤ 3

Sections → one page

One file, one Admin form. Keep shorter pages simple.

4+

Sections → individual modules

One module per section, with its own fields and media.

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.

The details deserve
a second look.

A first pass gets the site running. The fidelity loop brings the design closer, with measured comparisons until you're happy with the result.

  • Every route checked. Titles, text, images, redirects, language tags, noindex and analytics.
  • Desktop and mobile compared. Source and local screenshots at 1440px and 390px, with section measurements.
  • Forms submitted in a browser. A saved record or captured email backs the success message.
  • You approve the handoff. Reports, decisions, remaining gaps and a real Admin or MCP edit round-trip.

Source website

Local Grav site

CompareMeasureRefine
Diagram of the fidelity loop, not migration screenshots.
Routes passing
100%
Average source text coverage
100%
Main-template height difference
~1%

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

A little more under the hood.

The workflow is explicit, the scripts are rerunnable, and the important choices stay yours.

01All 13 checkpoints
  1. Confirm the plan. URL, folder, runtime and agent clients.
  2. Install Grav + Admin2. Start the server and verify Admin login.
  3. Connect API + MCP. Create the local launcher; verify an agent can list pages.
  4. Discover every route. Read robots and sitemaps, crawl links, detect soft 404s, redirects, languages and PDFs.
  5. Review the audit. Trackers and IDs, forms including popups, embeds, custom code, fonts and palette.
  6. Make the choices. Theme name, styling, languages, form delivery, CAPTCHA and analytics.
  7. Extract and import. Text, cards, galleries, video and modals; download media once and deduplicate by SHA-256.
  8. Build the pages. Frontmatter, blueprints, source provenance, shared sections and redirects. Lint with Grav's YAML parser.
  9. Create the theme. Measured tokens and source CSS, editable navigation and footer, optional Tailwind 4.
  10. Connect the forms. Grav Form pages with inline submission, selected delivery and browser tests.
  11. Handle analytics. Port approved tags only to the selected production hosts.
  12. Iterate to parity. Compare layout groups at desktop and mobile widths. Refine templates and named Admin fields.
  13. Verify and hand over. Route report, YAML lint, clean Grav log, a real edit, credentials location and remaining provider or licensing needs.

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.

02Your choices, defaults and safeguards

Runtime & agent access

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.

Theme & styling

Name your theme. Choose Tailwind 4 for ongoing design work or plain CSS with tokens before detailed styling begins. DESIGN.md records the decisions.

Languages

Native Grav multilang when hreflang maps translations, or separate trees per language prefix. Titles, descriptions, Open Graph and language tags come across.

Form delivery & success

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.

CAPTCHA

Grav's built-in Cap is the default: self-hosted, invisible and no keys required. Turnstile and reCAPTCHA are alternatives.

Analytics

Port on production hosts only, add consent gating, retain selected tags or drop them. Local and preview traffic stays out of production analytics.

  • Preserve source URLs. Ask before renaming; add 301 redirects for approved changes.
  • Keep authoring private. Admin2, API and MCP are authoring tools and should not be exposed in the production profile.
  • Protect local copies and secrets. Noindex meta and headers on preview hosts; no printed, logged or committed keys. SMTP passwords stay in environment variables.
  • Use real integrations. No guessed form endpoints or pretend success messages. Confirm copied font licenses before production.
  • Prefer Grav's built-ins. Form, Cap, Email, page media and native multilang. Theme JavaScript has no dependencies or jQuery.
03What ends up on disk
~/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.

04The scripts that do the work

Python uses its standard library; PHP uses Grav's YAML parser. Node runs MCP and, when needed, Tailwind or Playwright. Each script has --help.

ScriptPurpose
install_grav.shLatest Grav + Admin2, PHP and extension checks.
bootstrap_access.shAdmin, API key and MCP launcher. Reuses credentials unless rotation is requested.
crawl_site.pySitemaps, crawl, cached HTML, redirects, languages and PDFs.
audit_site.pyTrackers, forms, embeds, code, fonts and palette.
extract_content.pySections, blocks, shared content, site navigation and layout groups.
import_media.pyDownload once, deduplicate and assign page or shared media.
build_pages.pyPage tree, modules, frontmatter, languages, provenance and redirects.
scaffold_theme.pyStandalone theme, source CSS and design tokens, optional Tailwind.
build_forms.pyForm plan, Grav Form pages and CAPTCHA setup.
capture_pages.mjsSource and local screenshots, computed styles and section measurements.
verify_parity.pyRoute, content, media, forms, SEO and analytics checks.
grav_config.phpRead, merge and lint YAML using Grav's parser.
05What your machine needs

PHP 8.3+ or Docker

Extensions: curl ctype dom gd json mbstring openssl session simplexml xml zip. Recommended: intl yaml apcu opcache. Docker brings its own runtime.

Python 3.9+

Standard library only. No pip installation for crawling, extraction or page building.

Node 18+

For Grav MCP, Tailwind and Playwright. Installed as needed inside the migration project.

Your next site starts with a URL.

Install the skill. Bring a website. Make it yours in Grav.

Install the skill