Today, I decided to migrate my old WordPress site at weshipcode.com (over 1000 posts!) to Hugo, a fast static site generator. Instead of doing it manually, I used Cline (powered by xAI Code Fast 4.1 via OpenRouter) right inside VS Code. Combined with Gemini Flash for planning, this was a seamless experience using Plan Mode for strategy and Act Mode for execution.

The Planning Phase (Plan Mode)

Cline first explored the WordPress setup in /var/www/weshipcode:

  • Confirmed Hugo v0.152.2 installed.
  • Accessed the MySQL DB spiffy_release (1039 published posts/pages).
  • Listed plugins and checked wp-config.php.

We architected:

  1. Initialize Hugo site in weshipcode-hugo.
  2. PHP migration script to export posts/pages to Markdown with frontmatter (title, date, categories, tags, featured images).
  3. Copy uploads to static/wp-content/uploads.
  4. Clone PaperMod theme.
  5. Update Nginx for static serving + 301 redirect from naked domain.
  6. Document here!

Execution (Act Mode)

Cline used tools like execute_command, read_file, write_to_file, replace_in_file:

  • Created Hugo structure and config.
  • Ran php migrate.php – converted HTML to basic MD, preserved images.
  • Copied ~GBs of media.
  • Added theme, updated hugo.toml.

Challenges Encountered

Migration isn’t always smooth! We hit several roadblocks:

  1. Hugo Snap Permissions: The snap version of Hugo had issues accessing /var/lib/snapd/void, preventing builds. We fixed this by removing the snap and installing the extended binary directly to /usr/local/bin.
  2. YAML Parsing Errors: WordPress titles with double quotes caused Hugo build failures. We had to update the migration script to properly escape quotes in the frontmatter.
  3. Deprecated Theme Functions: My personal blog theme used resources.ToCSS, which was removed in newer Hugo versions. Cline identified this and refactored it to css.Sass.
  4. Homepage Configuration: Getting the PaperMod theme to list 1000+ posts on the homepage required fine-tuning hugo.toml (disabling profileMode and setting mainSections). We also had to ensure no _index.md was overriding the list view.
  5. Image Distortion: Images were initially distorted against their aspect ratio. We fixed this by adding custom CSS (max-width: 100%; height: auto;) in assets/css/extended.css.
  6. Author Attribution: The initial migration used a generic author name. We updated the script to pull the original display_name from the WordPress wp_users table to restore proper credit.
  7. About Page: We restored the original “About” page from WordPress and added it to the main navigation menu.
  8. URL Structure Refinement: We updated the permalink structure from the default date-based format to a cleaner /{category}/{title}/ structure, ensuring better SEO and consistency.
  9. Author Bio and Photo Migration: We went beyond just names and migrated full author biographies and profile photos. We also created dedicated author pages and made author names on posts clickable, linking directly to their bios.
  10. Broken Link Detection: We used a custom Node.js script to crawl the entire site and identify broken internal links, generating a comprehensive report to help clean up legacy URL issues.
  11. Advanced Pagination: We replaced the default “Prev/Next” navigation with a custom numbered pagination system (1 2 3 4 5) for better user experience across 1000+ posts.
  12. Integrated Search: We enabled PaperMod’s built-in search functionality, allowing users to quickly find content across the vast archive of posts.
  13. Branding Update: We updated the site title and footer to reflect the new branding, Spiffy.sg.
  14. Deep Media Audit and Restoration: We developed a script to compare broken links against the original WordPress uploads. This allowed us to automatically restore missing assets and fix malformed paths (like double slashes or absolute server paths) that were missed during the initial migration.
  15. Security Cleanup: By extracting all external links, we were able to identify and flag weird, spammy outgoing links (e.g., pharmaceutical spam) likely left behind from old WordPress hack attempts, allowing for a cleaner and safer site.

Nginx Update (new config):

server {
  listen 80;
  server_name weshipcode.com;
  return 301 http://www.weshipcode.com$request_uri;
}
server {
  listen 80;
  server_name www.weshipcode.com;
  root /var/www/weshipcode-hugo/public;
  # Static-optimized
}

Run sudo mv weshipcode-hugo/nginx-weshipcode.conf /etc/nginx/sites-enabled/weshipcode && sudo nginx -t && sudo systemctl reload nginx.

Hugo snap had permission issues (public dir empty), but fixable with hugo --destinationDir public.

Why AI Tools Rock

  • OpenRouter + Gemini Flash: Quick planning back-and-forth.
  • xAI Code Fast 4.1: Precise tool calls, iterative fixes (Node.js ES issue → PHP).
  • VS Code Integration: All in terminal, no context switch.
  • Cost-Effective: I spent around $10 on OpenRouter to complete this entire migration of over 1000 posts.

Pro Tip: You need to be specific and tell the AI exactly what you want. It might not migrate everything perfectly on the first pass (like author names or specific pages), so iterative feedback is key to getting the final result just right.

Retrospective

Looking back, it is a good idea to get the AI to list down all the assets from the database comprehensively before starting. This helps in identifying exactly what needs to be migrated (like custom user meta for photos and bios) and ensures nothing is missed in the initial plan.

Spiffy.sg before migration The original Spiffy.sg WordPress site before migration.

Spammy links identified Identifying spammy outgoing links from old hack attempts.

Migration done in ~2 hours! Check weshipcode.com soon. 🚀 #WeShipCode