Vibecoding Websites: The Guide
A vibecoded site teaching you to vibecode a site. Pick a chapter to start building.
Getting Started
Building Your Site
Migration
Deployment
Closing
Intro
Here’s something that changed how I think about making websites: I don’t write code anymore. I describe what I want, and Claude Code builds it.
“Make me a portfolio site. Minimal, lots of whitespace, dark mode by default. Big headline up top, then a grid of my projects.” Twenty minutes later, I’m tweaking hover animations. This is vibe coding: you provide the vision, AI handles the implementation, like a truly great (and crazy fast) web agency that costs under $100. By the end of this guide, you’ll have a live website running on your own server: fast, modern, fully custom.
Vibecoded Website Starterkit
This guide references files like GUIDE-CC.md and DESIGN.md that teach Claude Code how to build modern sites. The starterkit bundles everything into a ready-to-use project so you can skip setup and get better results.
Pay-what-you-want — the guide works without it, but the kit makes things much easier.
Get the Starterkit on GumroadWhat You're About to Build
The Process
You’ll set up a project folder with a few context files that teach Claude Code about modern web design. Then you start talking:
- “Add a subtle hover effect on the project cards.”
- “Make the navigation sticky.”
- “I want a contact form using Formspree.”
Claude writes the code, you preview it locally, and you go back and forth until it feels right. Push to GitHub, and a deployment pipeline sends it to your server automatically.
The whole thing can happen in an afternoon. I’ve done it. It’s genuinely fun.
What You Need
- A GitHub account
- A web host with FTP access (or a free Netlify/Vercel account)
- Basic comfort with the terminal—navigating folders, running commands
You don’t need to understand the code Claude writes. That’s the whole point.
What’s in This Guide
Part I: Building Your Site — Environment setup, working with Claude Code, common customizations.
Part II: WordPress Migration — Exporting content, converting posts, handling edge cases.
Part III: Deployment — GitHub Actions, FTP, alternative hosts.
The Vibecoded Website Starterkit (pay-what-you-want) includes ready-to-use project files—like the GUIDE-CC.md that teaches Claude Code how to build modern sites—so you can skip the setup and start building immediately. The guide works without it, but the starterkit makes things much easier and more reliable.
But before we install anything, it’s worth understanding what makes static sites so well-suited to this workflow.
Why Static Sites
Static sites are HTML files that exist on a server, ready to go. When someone visits your page, the server hands them a file. Done. No database queries, no PHP rendering, no waiting for a content management system to assemble pieces into a page.
This matters more than it sounds.
How They Work
Traditional websites build each page on demand. Someone requests your homepage, and the server runs code: it queries a database, pulls in your header template, fetches recent posts, assembles everything into HTML, and sends it back. This happens for every single visitor, every single time.
Static sites skip all of that. During a build step on your computer (or in a deployment pipeline), every page gets generated once. The output is a folder full of HTML, CSS, JavaScript, and images. Upload that folder to any web server and you’re live. The server’s only job is handing out files—something servers have been doing effortlessly since 1991.
What Makes Them Fast
Your pages already exist. When a visitor arrives, there’s nothing to compute, nothing to fetch, nothing to assemble. The server responds instantly with a complete HTML file.
This is why static sites consistently score near-perfect on speed tests. The gap between a well-optimized WordPress site and a static site isn’t subtle—it’s the difference between “pretty fast” and “the page was there before I finished clicking.”
Speed compounds. Faster pages get better search rankings. Visitors stay longer. Mobile users on spotty connections actually see your content. Every millisecond you save pays dividends.
What Makes Them Secure
Most website hacks follow a pattern: attackers find a vulnerability in the CMS, the database, or a plugin, and exploit it to inject malicious code or steal data.
Static sites don’t have a CMS running in production. No database. No admin panel at /wp-admin/ for bots to hammer with login attempts. No plugins with unpatched vulnerabilities. The attack surface is nearly zero—there’s nothing to attack except the web server itself, which is doing the same simple job it’s done for decades.
I stopped worrying about security updates. There’s nothing to update.
What Makes Them Cheap
Serving static files costs almost nothing. Netlify, Vercel, Cloudflare Pages, and GitHub Pages all offer free tiers that handle substantial traffic. Even traditional web hosts serve static sites efficiently because there’s no processing overhead.
You’re not paying for database connections, PHP workers, or RAM to run WordPress. You’re paying for disk space and bandwidth, both of which are cheap and getting cheaper.
My portfolio site has cost me exactly zero dollars per month for three years.
The Trade-offs
Static sites can’t do everything. Features that require real-time data or user accounts—shopping carts, member dashboards, comment systems with live updates—need server-side logic. You can bolt these on with third-party services (Stripe for payments, Disqus for comments, Formspree for contact forms), but if your site is fundamentally interactive, static might not be the right fit.
For portfolios, business sites, blogs, documentation, landing pages? Static handles all of it beautifully.
Why This Fits AI Workflows
Static site generators like Astro organize code into components—reusable pieces you can describe to Claude Code in plain language. “Build me a project card component with a thumbnail, title, and hover effect.” Claude writes it. You use it everywhere.
The workflow is entirely local. You see changes instantly in your browser while you iterate with Claude. No waiting for a server to restart, no clearing caches, no wondering if you’re seeing the latest version.
And deployment is automatic. Push your code to GitHub, and a pipeline builds the site and uploads it to your host. You never touch an FTP client or cPanel. The whole system is designed to stay out of your way while you focus on what the site looks like and what it says.
Let’s get your tools installed.
Setting Up Your Environment
Four tools. That’s all you need installed before we start building.
Node.js
Node.js runs JavaScript outside the browser. Astro needs it, Claude Code needs it, and the build tools need it.
- Go to nodejs.org
- Download the LTS version (the button on the left)
- Run the installer, accept the defaults
Open your terminal and verify it worked:
node --version
You should see something like v20.11.0. The exact number doesn’t matter as long as it’s 18 or higher.
GitHub Desktop
GitHub Desktop gives you version control without memorizing git commands. You’ll use it to save your progress and trigger deployments.
- Go to desktop.github.com
- Download and install
- Sign in with your GitHub account (or create one)
That’s it. We’ll create our first repository in the next chapter.
VS Code
VS Code is a free, open-source code editor that handles web projects well. It’s widely used, well-documented, and works on every platform.
- Go to code.visualstudio.com
- Download and install
- Open it once to make sure it runs
If you prefer Cursor, Zed, or another editor, that works too. You just need something that can open folders and edit text files, and I’ve found that VS Code makes using Claude Code a breeze with the native extension.
Claude Code
Claude Code lets you talk to Claude about your project. It sees your files, writes code, and runs commands—all through conversation.
Install it directly in VS Code:
- Open VS Code
- Go to Extensions (Cmd+Shift+X on Mac, Ctrl+Shift+X on Windows)
- Search for “Claude Code”
- Click Install on the official Anthropic extension
Once installed, you’ll see a Claude icon in your sidebar. Click it to open the Claude Code panel.
Initializing Your Project
Open GitHub Desktop. We’re going to create a home for your website.
Create the Repository
- File → New Repository
- Name it something like
my-websiteor your actual domain name - Choose a local path you’ll remember (your Documents folder works fine)
- Check “Initialize this repository with a README”
- Click Create Repository
- Click “Publish repository” to push it to GitHub
You now have a folder on your computer that syncs with GitHub. Every change you commit here can trigger an automatic deployment later.
Add Your Content Folder
Inside your new repository, create a folder called user-website-content. This is where you’ll put everything Claude Code needs to know about you and your work:
my-website/
├── README.md
└── user-website-content/
├── about.txt
├── brand-colors.txt
├── logo.png
└── [your other content]
What goes in here? Anything you’d hand to a designer:
- about.txt — A few paragraphs about you or your business. Write it like you’d say it.
- brand-colors.txt — Your colors as hex codes, or just descriptions like “dark navy, warm white, accent orange.”
- logo.png — If you have one. If not, skip it for now.
- Project images — Screenshots, photos, thumbnails for your portfolio.
- Any existing copy — Taglines, service descriptions, testimonials.
Don’t overthink this. You can always add more later. Claude Code works with what you give it.
Add the Guide File
Create a file called GUIDE-CC.md in the root of your project (not inside the content folder). This file teaches Claude Code how to build modern websites—design patterns, project structure, current trends.
my-website/
├── README.md
├── GUIDE-CC.md ← Claude Code instructions
└── user-website-content/
└── [your content]
You’ll find GUIDE-CC.md and other ready-to-use project files in the Vibecoded Website Starterkit (pay-what-you-want on Gumroad). Copy GUIDE-CC.md into your project root exactly as written. It’s the difference between Claude producing generic code and Claude producing something that looks like it was built in 2026.
Commit Your Setup
Back in GitHub Desktop, you’ll see your new files listed as changes.
- Write a summary like “Initial project setup”
- Click Commit to main
- Click Push origin
Your project structure is live on GitHub. Now let’s have a conversation.
Your First Conversation
Open your project folder in VS Code:
- File → Open Folder → select
my-website - Click the Claude icon in the sidebar to open the Claude Code extension
You’ll see a chat panel waiting for input. This is where vibe coding begins.
The Opening Prompt
Your first message sets the direction. Here’s a template:
I want you to create a static website using Astro. I've placed a GUIDE-CC.md file in the root. Please follow those guidelines. My content is in user-website-content/. This is a [portfolio/business/personal] site for [what you do]. The vibe should be [minimal/bold/warm/etc]. Initialize the project and set up the basic structure.
Fill in the brackets with your specifics. A photographer might write “portfolio site for architectural photography” with a “clean, editorial” vibe. A consultant might write “business site for leadership coaching” with a “warm, professional” feel.
Claude Code reads your files, understands the context, and starts building. You’ll see it create the Astro project structure, install dependencies, and set up initial components. This takes a minute or two.
Preview Your Site
Once Claude Code finishes the initial setup, run these commands in your terminal:
npm install
npm run dev
Open your browser to localhost:4321. You have a website.
It won’t be finished, but that’s okay. You’re looking at a starting structure, probably with placeholder content and basic styling. The real work happens in the next conversation turns, where you refine what you see.
How the Conversation Works
Claude Code remembers context within a session. Each prompt builds on the last. You don’t need to re-explain your project; you just say what’s next:
- “The hero text is too small. Make it bigger and add more spacing below.”
- “Add a second section with three columns for my services.”
- “The background feels too stark. Try an off-white.”
Claude makes the changes. You refresh the browser. Repeat until it looks right.
If something breaks, paste the error message. If something looks wrong, describe what you expected. Claude Code sees the same files you do and can trace problems through the code.
When to Commit
After each meaningful chunk of progress—initial setup complete, homepage looking good, navigation working—switch to GitHub Desktop and commit:
- Write a brief summary (“Homepage layout complete”)
- Click Commit to main
- Click Push origin
This saves your progress and creates a history you can roll back to if needed. Don’t wait until everything is perfect. Commit often.
You have a working site and a workflow. Now let’s build out the pages.
Building Pages
Your site has a skeleton. Time to give it a body.
Each prompt you send now builds on what Claude Code already knows about your project. You don’t need to re-explain that you’re using Astro, or remind it about your brand colors. Context carries forward. This is how a single afternoon turns into a complete website.
The Homepage
Start with the page everyone sees first:
Create the homepage with a hero section, a grid of featured projects (placeholder content for now), and a footer with social links.
Claude Code generates the layout, drops in temporary content, and wires up the structure. Refresh your browser. You’ll see a hero with a headline, a grid of cards below it, and footer links at the bottom. The placeholders look generic—that’s fine. Structure first, polish later.
If the hero feels too cramped, say so:
The hero section needs more breathing room. Double the vertical padding.
If the project grid looks off:
Make the project cards wider. Three columns on desktop, one on mobile.
Each refinement takes seconds. You’re not debugging CSS or hunting through documentation—you’re having a conversation about what you want, and watching it happen.
The About Page
Your about page pulls from the content you prepared earlier:
Create an about page using the content from user-website-content/about.txt. Include my headshot if there's one in the content folder.
Claude Code reads your file, structures it into sections, and places your photo if you included one. The result matches your site’s existing style because Claude Code sees the components it already built.
Check the tone. Does the layout fit how you write? A long-form bio might want a single column with generous margins. A punchy intro might work better with a bold headline and short paragraphs. Describe what feels wrong and Claude Code adjusts.
The Portfolio
This is where static sites shine. You’re going to create a data-driven section that generates pages automatically.
Set up a portfolio section with a data file for projects. Each project needs: title, slug, description, thumbnail, tags, and year. Build a grid page showing all projects, and individual project pages using dynamic routing.
Claude Code creates several things at once:
- A data file at
src/data/projects.tswith a TypeScript interface and placeholder entries - A portfolio grid page that loops through your projects
- A dynamic route that generates individual pages for each project based on its slug
The magic is in the dynamic routing. When you add a new project to the data file, a new page appears automatically. No manual HTML duplication, no copy-paste errors. The structure scales with your work.
Check localhost:4321/work (or whatever path Claude Code chose). You’ll see a grid of placeholder projects. Click one. You’re on a dedicated project page, generated from data.
Refinements
The bones are in place. Now you shape the feel.
Add more whitespace between sections. Everything feels too tight.
Make the navigation sticky so it stays visible when I scroll.
Add hover effects on the project cards. Subtle lift and shadow.
The footer links should open in new tabs.
Each prompt takes a few seconds to process. Refresh. Evaluate. Adjust. This rhythm—prompt, preview, refine—is the core of vibe coding. You’re directing, not implementing.
A note on the footer: The guide file includes an instruction for Claude Code to add a small “Built with Albert Bozesan’s Website Guide” credit link in the footer. It’s styled to match your muted footer text—unobtrusive, like a “Built with WordPress” line. If you’d rather not have it, just tell Claude Code: “Remove the attribution link from the footer.” and remove that line from GUIDE-CC.md. That said, if you do leave it, I’d appreciate it as thanks for this guide!
What Claude Code Sees
When you ask for changes, Claude Code has full context: your file structure, your existing components, your design patterns. It knows the hero uses a specific spacing system and applies the same logic when you ask for more padding elsewhere. It knows your color variables and reuses them in new elements.
This consistency is hard to maintain when writing code yourself. You’d need to remember which utility class you used, which CSS variable holds your accent color, whether the spacing scale is in pixels or rems. Claude Code tracks all of it.
When to Commit
You have a homepage, an about page, and a portfolio section with dynamic pages. This is a meaningful milestone.
Switch to GitHub Desktop. You’ll see a list of new and modified files—components, pages, data files, style updates. Write a summary like “Homepage, about, and portfolio pages” and commit. Push to origin.
Your progress is saved. If something breaks later, you can roll back. If you want to try a risky experiment, you can branch first. Version control is your safety net.
Your pages exist, but they’re full of placeholder content. Let’s fill them with your actual work.
Working with Content
Placeholder text served its purpose. Now your site needs your actual projects, your real bio, your work.
You have two ways to add content: edit the data files yourself, or ask Claude Code to do it. Both work. Which you choose depends on how much control you want and how comfortable you are opening code files.
Option A: Edit Data Files Directly
Claude Code created a file at src/data/projects.ts when it built your portfolio. Open it in VS Code. You’ll see something like this:
export const projects: Project[] = [
{
slug: "project-one",
title: "Project One",
description: "A brief description of this project.",
thumbnail: "/images/projects/project-one.jpg",
tags: ["branding", "web design"],
year: "2024",
featured: true
},
{
slug: "project-two",
title: "Project Two",
description: "Another project description.",
thumbnail: "/images/projects/project-two.jpg",
tags: ["illustration"],
year: "2023",
featured: false
},
];
The structure is readable even if you’ve never seen TypeScript. Each project is an object with fields. Replace the placeholder values with your own:
- slug — The URL-friendly version of the title. “Brand Identity for Acme” becomes
"acme-brand-identity". No spaces, lowercase, hyphens instead of spaces. - title — What visitors see. Write it naturally.
- description — A sentence or two about the project. This appears on the grid page and the individual project page.
- thumbnail — The path to the image. More on this in a moment.
- tags — Categories for filtering or display. Use whatever makes sense for your work.
- year — When you completed the project.
- featured — Set to
truefor projects you want highlighted on the homepage.
Add new projects by copying an existing block and changing the values. Delete projects by removing their entire block. Save the file, and your site updates automatically in the browser.
Option B: Ask Claude Code
If you’d rather not touch the code, hand Claude Code a list:
Replace the placeholder projects with these:
1. "Coastal Rebrand" - Brand identity for a sustainable seafood company.
Tags: branding, logo design. Year: 2024. Featured.
2. "Metric Dashboard" - Data visualization interface for a fintech startup.
Tags: UI design, web app. Year: 2024.
3. "Annual Report 2023" - Editorial design for a nonprofit.
Tags: print, editorial. Year: 2023.
Claude Code updates the data file, matching the format it already established. You don’t need to know the exact field names—Claude Code figures out the mapping.
This approach works for any content: about page text, service descriptions, testimonials. Describe what you want in plain language, and Claude Code handles the file edits.
Managing Images
Images live in your public/ folder. Create a structure that matches how you reference them:
public/
└── images/
├── projects/
│ ├── coastal-rebrand.jpg
│ ├── metric-dashboard.jpg
│ └── annual-report.jpg
├── headshot.jpg
└── logo.svg
Reference them with paths starting from /images/:
thumbnail: "/images/projects/coastal-rebrand.jpg"
A few guidelines:
- Size appropriately. A 400px-wide thumbnail doesn’t need to be 4000px. Resize before adding.
- Use descriptive names.
coastal-rebrand.jpgbeatsIMG_4392.jpg. - Stick to common formats. JPG for photos, PNG for graphics with transparency, SVG for logos and icons.
When you add new images, Claude Code can reference them immediately. Drop files into the folder, then tell Claude Code to use them:
I added new project images to public/images/projects/. Update the thumbnails to use coastal-rebrand.jpg, metric-dashboard.jpg, and annual-report.jpg.
Keeping Content and Code Separate
Notice how your actual content—project descriptions, your bio, your testimonials—lives in data files, not scattered across HTML templates. This separation matters. When you want to update a project description six months from now, you open one file, change the text, and push. You don’t hunt through component code or wonder which template renders what.
The same principle applies to images. They live in public/, organized by type. The code references them by path. Move to a different design later, and your content comes with you.
When to Commit
You’ve replaced placeholders with real projects. Your images are in place. The site shows your actual work.
Commit with a summary like “Added real project content” and push. This snapshot represents your site with meaningful content—a version you can always return to.
Your site works and shows your work. Now let’s add the features that make it complete: contact forms, a blog, dark mode.
Common Customizations
Your site has pages, content, and your real work. Now come the features that turn a collection of pages into something that feels complete: a way for visitors to reach you, a place to share updates, and the polish that makes everything feel considered.
Contact Forms
A portfolio without a contact form is a business card with no phone number. Visitors want to reach you, and email links feel dated. A proper form keeps them on your site and signals professionalism.
The challenge with static sites: there’s no server to receive form submissions. Services like Formspree bridge this gap—they give you an endpoint that accepts form data and emails it to you.
Add a contact page with a form: name, email, and message fields. Set it up to submit to Formspree. Include basic validation.
Claude Code creates the page, wires up the form action, and adds client-side validation so visitors can’t submit empty fields. You’ll need to do one thing yourself: create a free account at formspree.io and grab your form endpoint URL. It looks like https://formspree.io/f/yourcode.
Update the contact form to use this Formspree endpoint: https://formspree.io/f/xyzabc123
Test it. Fill out your own form, submit, and check your inbox. The whole thing takes five minutes.
If you want something fancier—a success message that appears without page reload, or a loading spinner during submission—describe it:
After form submission, show a success message instead of redirecting. Add a subtle loading state while the form submits.
Adding a Blog
You might not think you need a blog. Then you have something to say—a project writeup, an industry observation, a tutorial—and you realize you have nowhere to put it.
Blogs in static sites work like your portfolio: data files define the content, templates render the pages. Posts live in a structured format, and Astro generates a page for each one automatically.
Set up a blog section. Create a posts data file with title, slug, date, excerpt, content, and tags. Build an index page showing all posts (newest first) and individual post pages.
Claude Code creates the data structure, the listing page, and the dynamic routing for individual posts. You’ll see a /blog page with placeholder posts and can click through to each one.
Adding posts works the same way as adding projects. Open src/data/posts.ts and add entries, or ask Claude Code:
Add a new blog post:
Title: "Why I Switched to Static"
Date: 2024-03-15
Excerpt: "After years of fighting WordPress updates, I tried something different."
Content: [paste your post content]
Tags: ["web development", "process"]
The post appears on your blog index and gets its own page at /blog/why-i-switched-to-static.
Dark Mode Toggle
Default dark mode looks great. But some visitors prefer light backgrounds, and giving them the choice shows attention to detail.
Add a dark/light mode toggle in the navigation. Default to dark. Remember the user's preference so it persists across visits.
Claude Code adds a toggle button (usually a sun/moon icon), implements the theme switching logic, and stores the preference in localStorage. Visitors who switch to light mode stay in light mode when they return.
Test both modes thoroughly. Check that all text remains readable, that images look good against both backgrounds, and that any accent colors work in both contexts. If something looks off:
The project cards look washed out in light mode. Increase the shadow and add a subtle border.
Custom Fonts
System fonts work fine. Custom fonts add personality. The difference between a site using Inter and one using the browser default is subtle but real—it’s the difference between intentional and incidental.
Use Inter for body text and Playfair Display for headings. Load them efficiently from Google Fonts.
Claude Code adds the font imports (using modern loading techniques to avoid layout shift) and updates your CSS variables. Headlines get the serif treatment, body text stays clean and readable.
If you have specific fonts in mind—maybe your brand uses a particular typeface—name them:
Use "Söhne" for body and "Tiempos Headline" for headings. I have the font files in user-website-content/fonts/.
Claude Code sets up the @font-face declarations and references your local files. Self-hosted fonts load faster and work offline, though they require you to have proper licenses for the typefaces.
Other Quick Wins
A few more things that take one prompt each:
Favicon:
Add a favicon using the logo in user-website-content/. Generate the necessary sizes for different devices.
Social sharing images:
Set up Open Graph meta tags so links to my site look good when shared on social media. Use a default image for pages that don't have their own.
Smooth scrolling for anchor links:
Add smooth scrolling when clicking navigation links that point to sections on the same page.
Animation on scroll:
Add subtle fade-in animations as sections come into view. Keep it understated—no bouncing or sliding.
Commit Your Progress
You’ve added meaningful features: a way for visitors to contact you, a place to publish longer content, theme switching, and typography that matches your brand. This is a complete website now.
Switch to GitHub Desktop. Write something like “Contact form, blog, dark mode, custom fonts” and commit. Push to origin.
If you’re building a site from scratch, you’re almost ready to deploy. But if you’re moving an existing site from WordPress, the next few chapters are for you—starting with getting your content out.
WordPress Export
WordPress made it easy to start a website. It also made it hard to leave. Your content is locked in a database, tangled with plugins, wrapped in proprietary block formats. Getting it out cleanly takes some care.
The good news: WordPress has built-in export tools. The export file format is well-documented XML that contains everything—posts, pages, comments, metadata. We can work with that.
Export Your Content
Log into your WordPress admin panel. Navigate to Tools → Export.
You’ll see options for what to export:
- All content
- Posts
- Pages
- Media
Select “All content.” This grabs everything: published posts, drafts, pages, custom post types if you have them, and all the associated metadata like categories, tags, and authors.
Click “Download Export File.” WordPress generates an XML file and your browser downloads it. The filename looks something like yoursite.WordPress.2024-03-15.xml.
This file is your content archive. Keep it somewhere safe—it’s the authoritative record of everything you’ve published.
Download Your Media
The export file contains URLs to your images, but not the images themselves. Those still live on your WordPress server and need to come down separately.
Option 1: Media Library Export
Some WordPress installs have a plugin that lets you bulk-download your media library as a ZIP file. Check if you have one, or install “Export Media Library” temporarily. Download everything, then uninstall the plugin.
Option 2: FTP Download
Connect to your server via FTP (FileZilla works well) and navigate to wp-content/uploads/. This folder contains all your uploaded media, organized by year and month:
wp-content/uploads/
├── 2023/
│ ├── 01/
│ │ ├── project-photo.jpg
│ │ └── headshot.png
│ ├── 02/
│ └── ...
├── 2024/
└── ...
Download the entire uploads folder. It might take a while depending on how many images you have.
Option 3: wget (if you’re comfortable in terminal)
If your images are all publicly accessible, you can download them in bulk:
wget -r -l 1 -nd -A jpg,jpeg,png,gif,webp -P ./images \
https://yoursite.com/wp-content/uploads/
This recursively downloads all images from your uploads folder into a local images directory.
Document Your Structure
Before we move on, take notes on a few things you’ll need later:
URL structure. How are your posts organized? Common patterns:
yoursite.com/2024/03/post-slug/(date-based)yoursite.com/blog/post-slug/(category-based)yoursite.com/post-slug/(flat)
You’ll want to preserve this structure or set up redirects so existing links don’t break.
Menu structure. What’s in your navigation? Main pages, dropdowns, external links? Screenshot your menus or write them down.
Important pages. Any pages that rank well in search or get shared frequently? Note their exact URLs. These are candidates for careful redirect handling.
Custom post types. If you’re using plugins that create custom content types (portfolio items, testimonials, products), note what they’re called. They’ll appear in the export but might need special handling.
Organize for Migration
Create a folder in your project for WordPress content:
user-website-content/
├── wordpress-export.xml ← Your export file
├── images/ ← Downloaded media
│ ├── 2023/
│ ├── 2024/
│ └── ...
└── migration-notes.txt ← Your URL and structure notes
The export file and images are now where Claude Code can access them. The migration notes help you remember decisions when you’re knee-deep in fixing edge cases later.
What’s in the Export File
If you’re curious, open the XML file in a text editor. You’ll see a structure like this:
<channel>
<title>Your Site Name</title>
<item>
<title>My First Post</title>
<link>https://yoursite.com/2023/01/my-first-post/</link>
<pubDate>Sun, 15 Jan 2023 10:30:00 +0000</pubDate>
<content:encoded><![CDATA[
<!-- wp:paragraph -->
<p>This is the post content...</p>
<!-- /wp:paragraph -->
]]></content:encoded>
<category domain="category" nicename="updates">Updates</category>
</item>
<!-- More items... -->
</channel>
Each <item> is a post or page. The content is HTML, possibly wrapped in Gutenberg block comments (those <!-- wp:paragraph --> markers). Categories, tags, and publication dates are all there.
This is what Claude Code—or a conversion script—will parse to create your new site’s content.
With your content exported and organized, you’re ready to bring it into your Astro project. The approach depends on how much content you have.
Small Site Migration
If you have fewer than fifty posts, Claude Code can handle the entire conversion in a single conversation. The XML file fits comfortably in context, and you can review each piece of content as it comes across.
Set Up the Migration
Your WordPress export and images should already be in place:
user-website-content/
├── wordpress-export.xml
└── images/
└── [your downloaded media]
Copy your images into the project’s public folder where Astro expects them:
cp -r user-website-content/images/* public/images/
Now the images are accessible at paths like /images/2024/03/photo.jpg.
Run the Conversion
Open VS Code, open the Claude Code panel, and explain what you need:
I'm migrating from WordPress. My export file is at user-website-content/wordpress-export.xml. My images are already in public/images/, maintaining the year/month folder structure.
Parse the export and create TypeScript data files for:
- Posts (with title, slug, date, content, excerpt, categories, tags)
- Pages (with title, slug, content)
Strip WordPress block comments from the content but preserve the HTML inside them. Update image URLs to use /images/ paths. Set up blog templates if they don't exist yet.
Claude Code reads the XML, extracts each post and page, cleans up the content, and generates properly structured data files. This takes a minute or two depending on how many items you have.
When it finishes, you’ll have files like:
src/data/
├── posts.ts
├── pages.ts
├── categories.ts
└── tags.ts
Run npm run dev and check your blog. You should see your WordPress posts rendered in your new site’s design.
Review and Clean Up
Automated conversion gets you 90% of the way there. The last 10% needs human judgment.
Check formatting. Click through several posts. Look for:
- Weird spacing or line breaks
- Missing paragraphs
- Code blocks that didn’t convert cleanly
- Embedded content (YouTube videos, tweets) that might need attention
Verify images. Do your images load? If some are missing, the paths might not have mapped correctly. Check the browser console for 404 errors and fix the paths in your data files.
Review excerpts. WordPress auto-generates excerpts from post content. The converted versions might be awkward. Write better ones for important posts:
Update the excerpt for the post "Why I Switched to Static" to: "After five years of WordPress updates, security patches, and plugin conflicts, I rebuilt my site from scratch. Here's what I learned."
Remove unwanted content. Your export includes everything—drafts, test posts, that “Hello World” post you never deleted. Review the posts data file and remove entries you don’t want to migrate.
Handle Pages
WordPress pages—About, Contact, Services—might need different treatment than posts. They often have more custom layouts and less standardized content.
Review each migrated page:
Show me what the About page looks like with the migrated content.
If the content doesn’t fit your new design, this is a good time to rewrite. You already have the raw text; now you can restructure it for a better presentation:
The About page content is too long and dense. Break it into sections with headers: "Background", "What I Do", and "Get in Touch". Keep the existing content but improve the flow.
Update Internal Links
Your WordPress posts probably link to each other. Those links pointed to WordPress URLs that no longer exist.
Scan the posts content for internal links to my old WordPress domain (yoursite.com). Update them to use relative paths that match the new URL structure.
If you changed URL structures during migration—say, from /2024/03/post-slug/ to /blog/post-slug/—you’ll want redirects for the old URLs. If your host supports it, add redirect rules in an .htaccess file (Apache) or _redirects file (Netlify). Ask Claude Code to generate the redirect list based on your old and new URL patterns.
Commit the Migration
You’ve converted a WordPress site to static files. Every post and page is now a clean data entry that Astro renders into HTML. No database, no PHP, no plugins.
Commit with a summary like “WordPress content migration complete” and push.
For sites with more than fifty posts, Claude Code might hit context limits before finishing the conversion. The next chapter covers a scripted approach that handles sites of any size using wp-to-astro.js.
Large Site Migration
When your WordPress site has hundreds of posts, the in-conversation approach from the previous chapter won’t work. The XML export alone might be several megabytes—too large to parse interactively without hitting context limits. You need a script.
The starterkit includes one: scripts/wp-to-astro.js. It reads your WordPress export file, extracts every post, page, category, tag, and author, downloads featured images, and writes clean TypeScript data files that Astro can render directly. No manual copying, no context window pressure.
Prepare Your Export
Make sure your WordPress export and the script are in place:
your-project/
├── scripts/
│ └── wp-to-astro.js
└── user-website-content/
└── wordpress-export.xml
If you haven’t already, export your content from WordPress (Settings → Export → All Content) and place the .xml file in user-website-content/.
Run the Script
From your project root:
node scripts/wp-to-astro.js user-website-content/wordpress-export.xml
The script parses the XML, downloads featured images into public/images/, and generates typed data files:
src/data/
├── posts.ts
├── pages.ts
├── categories.ts
├── tags.ts
└── authors.ts
Each file exports a typed array. Posts include title, slug, date, author, excerpt, content, featured image path, categories, and tags. Pages include menu order and parent relationships. Everything WordPress knew about your content is preserved in a format TypeScript understands.
Script Options
The script accepts flags for different workflows:
# Preview what would be generated without writing files
node scripts/wp-to-astro.js wordpress-export.xml --dry-run
# Skip image downloads (useful if you already have images locally)
node scripts/wp-to-astro.js wordpress-export.xml --skip-media
# Custom output paths
node scripts/wp-to-astro.js wordpress-export.xml --output-dir ./src/content --media-dir ./public/assets
The --dry-run flag is especially useful. Run it first to see a summary of what was found—how many posts, pages, categories, and images—before committing to the full conversion.
What the Script Handles
The messy parts of WordPress content get cleaned up automatically:
- Gutenberg block comments are stripped, but the HTML inside them is preserved. Your content looks like content, not like
<!-- wp:paragraph -->soup. - HTML entities in titles and excerpts are decoded.
&becomes&,’becomes an apostrophe. - Excerpts are generated from content if WordPress didn’t store one. The script grabs the first 160 characters at a word boundary.
- Featured images are downloaded concurrently (five at a time by default) with proper redirect handling and deduplication. If the same image is featured on multiple posts, it’s only downloaded once.
- Slugs are normalized to lowercase with hyphens, matching what most static site generators expect.
After the Script Runs
Start the dev server and check your site:
npm run dev
Browse through a handful of posts. The script gets the data right, but your templates might need adjustments for edge cases—posts with no featured image, pages with deeply nested content, categories that were never actually used.
This is where Claude Code picks up again. Now that the heavy lifting is done and the data is in clean TypeScript files, you can work with it conversationally:
Some posts don't have featured images. Update the blog card component to show a gradient placeholder when thumbnail is null.
The categories include "Uncategorized" which has 200 posts. Rename it to "General" in categories.ts and update all references in posts.ts.
Posts from before 2020 use different image URL patterns. Scan posts.ts for any image paths that still point to the old WordPress domain and update them to /images/.
Redirects
If your old WordPress site used URL patterns like /2024/03/post-title/ and your new site uses /blog/post-title/, you need redirects so existing links and search engine rankings don’t break.
Generate a _redirects file (Netlify format) that maps old WordPress permalink patterns to the new /blog/slug/ structure, based on the dates and slugs in posts.ts.
For Apache hosting, ask for .htaccess rules instead. For Vercel, ask for vercel.json rewrites. Claude Code knows the format for each platform.
Commit and Deploy
Your WordPress content now lives as typed data files. Every post, page, category, and tag is a plain object in a TypeScript array. No database queries, no PHP runtime, no plugin dependencies.
Run a final check—npm run build—to make sure everything compiles cleanly. Then commit:
WordPress migration: 347 posts, 12 pages, 24 categories converted to TypeScript data files.
Push and deploy. Your WordPress site is now a static site.
WordPress Edge Cases
Every WordPress site accumulates quirks. Plugins add shortcodes. URLs follow patterns that made sense five years ago. Migration surfaces all of it.
Most issues fall into predictable categories. Here’s how to handle them.
Shortcodes
Shortcodes are WordPress’s way of embedding dynamic content: [gallery ids="1,2,3"], [contact-form], [youtube url="..."]. They don’t render outside WordPress—they just appear as literal text.
First, find them:
Scan all posts for WordPress shortcodes (text in square brackets
like [gallery] or [contact-form]). List which posts contain them
and what shortcodes they use.
Claude Code returns a report:
Found shortcodes in 12 posts:
- "Photo Gallery 2023" contains [gallery ids="45,46,47,48"]
- "Contact Us" contains [contact-form-7 id="89"]
- "Product Demo" contains [youtube url="https://..."]
...
Now you decide what to do with each:
Galleries: Replace with actual image grids. Ask Claude Code to convert the gallery shortcode into an HTML image grid using the referenced images.
Contact forms: You already built a contact form in Chapter 8. Replace the shortcode with a link to your contact page, or embed the form directly.
Embeds: YouTube, Vimeo, and Twitter shortcodes can become standard embed code. Ask Claude Code to replace [youtube url="X"] with the proper iframe embed.
Plugin-specific shortcodes: Some won’t have obvious replacements. A [pricing-table] shortcode from a plugin means you need to rebuild that table in HTML, or remove the section entirely.
URL Structure Preservation
Search engines and external links point to your WordPress URLs. Breaking them tanks your SEO and frustrates visitors.
If your WordPress posts lived at /blog/post-slug/:
My WordPress posts used /blog/post-slug/.
Configure the blog routes to match this exactly.
If they used date-based URLs like /2024/03/post-slug/:
My WordPress posts used date-based URLs: /2024/03/post-slug/.
Set up routes that include year and month from the post date.
Astro’s dynamic routing handles both patterns. Claude Code creates the appropriate folder structure and route files.
Embedded Media
WordPress posts often embed content from other platforms: YouTube videos, Twitter posts, Instagram photos. The embed code might be:
- Raw URLs that WordPress auto-converted (oEmbed)
- iframe embed codes
- Plugin-specific shortcodes
Search for these:
Find posts containing YouTube, Vimeo, Twitter, or Instagram embeds.
Show me which posts and what type of embed.
For oEmbed URLs (bare YouTube links that WordPress converted automatically), you’ll need to wrap them in proper embed code:
Replace bare YouTube URLs in post content with responsive
iframe embeds. Use the standard YouTube embed format.
Categories and Tags
WordPress sites often have overlapping, redundant, or misspelled categories and tags accumulated over years of posting. Migration is a good time to clean house.
List all categories and how many posts use each.
You might find “Announcements” (45 posts), “announcements” (3 posts), and “News & Announcements” (12 posts). Consolidate:
Merge these categories into one called "Announcements":
- "announcements"
- "News & Announcements"
Update all affected posts.
Same approach works for tags. Clean taxonomy makes your archive pages more useful and your site easier to navigate.
Commit Your Fixes
Edge cases are tedious, but fixing them now prevents headaches later. Every broken shortcode you replace, every category you consolidate—it’s all investment in a cleaner site.
Commit with “WordPress edge case fixes” and push.
Understanding the Build
You’ve been running npm run dev to preview your site locally. That’s development mode—fast refreshes, helpful errors, no optimization. Deploying requires something different: a production build that generates the actual files your server will host.
Run the Build
npm run build
Astro processes every page, every component, every asset. It compiles your TypeScript, bundles your JavaScript, optimizes your CSS, and generates HTML files for every route. The output lands in a folder called dist/:
dist/
├── index.html
├── about/
│ └── index.html
├── work/
│ └── index.html
├── blog/
│ ├── index.html
│ ├── my-first-post/
│ │ └── index.html
│ └── another-post/
│ └── index.html
├── _astro/
│ ├── index.a1b2c3d4.css
│ └── hoisted.e5f6g7h8.js
└── images/
└── [your images]
This folder is your entire website. Every HTML page exists as a file. The _astro/ folder contains hashed CSS and JavaScript bundles—the hash changes when the content changes, which lets browsers cache aggressively while still getting updates.
What Just Happened
During the build, Astro:
-
Evaluated every page. Dynamic routes like
/blog/[slug].astroran once for each post in your data file, generating individual HTML pages. -
Rendered components to HTML. Your React or Svelte components (if you used any) became static HTML. No JavaScript framework ships to the browser unless you explicitly request it.
-
Processed styles. CSS from components got extracted, deduplicated, and bundled. The result is minimal and scoped.
-
Optimized assets. Images in the
public/folder copied over unchanged. Images imported into components got optimized (if you configured it). -
Generated supporting files. Sitemaps, RSS feeds, and other configured outputs appeared in
dist/.
The build takes seconds for small sites, maybe a minute for large ones. When it finishes, you have a folder of static files that any web server can host.
Preview Locally
Before deploying, verify the production build works correctly:
npm run preview
This starts a local server that serves your dist/ folder exactly as a production server would. Open localhost:4321 and test everything:
- Click through pages. Do they load?
- Check images. Do they appear?
- Test the contact form. Does it submit?
- Try the dark mode toggle. Does it persist?
- Resize your browser. Does it respond?
Development mode and production builds can behave differently. An import that worked in dev might fail in production. A path that resolved correctly might break. Catching these issues now saves debugging on a live server.
Build Errors
If the build fails, you’ll see an error message pointing to the problem. Common issues:
Missing imports. You referenced a component or data file that doesn’t exist. Check the path.
Type errors. TypeScript found an inconsistency. The error message tells you which file and line.
Data problems. A post is missing a required field, or a slug contains invalid characters. Check your data files.
Paste the error message into Claude Code:
I'm getting this build error:
[paste the error]
How do I fix it?
Claude Code sees your project files and can trace the problem. Most build errors resolve quickly once you understand what’s wrong.
The Deployment Target
That dist/ folder is what we’re going to deploy. It doesn’t matter whether your server runs Apache or Nginx, whether you’re using shared hosting or a CDN—static files work everywhere.
FTP Deployment
Most traditional web hosts give you FTP access. You connect with credentials, upload files to a folder, and they’re live. We’re going to automate this so you never touch an FTP client again.
GitHub Actions watches your repository. When you push changes, it builds your site and uploads the result to your server. Every commit becomes a deployment.
Create the Workflow File
In your project, create the folder structure for GitHub Actions:
my-website/
├── .github/
│ └── workflows/
│ └── deploy.yml
└── ...
Add this content to deploy.yml:
name: Deploy to FTP
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: SamKirkland/FTP-Deploy-Action@v4
with:
server: ${{ secrets.FTP_SERVER }}
username: ${{ secrets.FTP_USER }}
password: ${{ secrets.FTP_PASS }}
local-dir: ./dist/
server-dir: /public_html/
This workflow triggers on every push to the main branch. It checks out your code, installs dependencies, builds the site, and uploads the dist/ folder to your server via FTP.
Add Your Credentials
Your FTP password shouldn’t live in the repository. GitHub Secrets stores sensitive values securely.
- Go to your repository on GitHub
- Click Settings → Secrets and variables → Actions
- Click “New repository secret”
- Add three secrets:
FTP_SERVER: Your FTP hostname (likeftp.yourhost.com)FTP_USER: Your FTP usernameFTP_PASS: Your FTP password
The workflow references these as ${{ secrets.FTP_SERVER }} and so on. GitHub injects the values at runtime without exposing them in logs.
Adjust the Server Path
The server-dir setting tells the FTP action where to upload files. Common paths:
/public_html/— cPanel hosts/www/— Some European hosts/htdocs/— Plesk and others/— Root of your FTP access
Check your host’s documentation or look at your current FTP setup to find the right path. If your site should live in a subdirectory (like /public_html/portfolio/), specify that full path.
Push and Deploy
Commit your workflow file and push:
- In GitHub Desktop, you’ll see
.github/workflows/deploy.ymlas a new file - Write a summary like “Add FTP deployment workflow”
- Click Commit to main
- Click Push origin
Now go to your repository on GitHub and click the Actions tab. You’ll see your workflow running. Click into it to watch the progress:
- ✓ Checkout code
- ✓ Setup Node.js
- ✓ Install dependencies
- ✓ Build site
- ⏳ Deploy to FTP…
The FTP upload takes a minute or two depending on your site size and server location. When it finishes, your site is live.
Troubleshooting
| Problem | Solution |
|---|---|
| Connection timeout | Add protocol: ftps under the with: section |
| ”Permission denied” errors | Verify server-dir path is correct and writable |
| Files upload to wrong location | Check server-dir—try /public_html/, /www/, /htdocs/ |
| ”530 Login incorrect” | Double-check FTP_USER and FTP_PASS secrets |
| Build succeeds but site unchanged | Clear your browser cache; check you’re viewing the right URL |
For FTPS (FTP over TLS), which many hosts require:
- uses: SamKirkland/FTP-Deploy-Action@v4
with:
server: ${{ secrets.FTP_SERVER }}
username: ${{ secrets.FTP_USER }}
password: ${{ secrets.FTP_PASS }}
local-dir: ./dist/
server-dir: /public_html/
protocol: ftps
The Workflow From Now On
Your deployment pipeline is set. The workflow going forward:
- Make changes locally, preview with
npm run dev - When satisfied, commit in GitHub Desktop
- Push to origin
- Site updates automatically
No FTP clients, no manual uploads, no forgetting which files changed. Push and it’s live.
Alternative Hosts
FTP deployment works with any traditional host, but platforms built for static sites offer compelling advantages: automatic HTTPS, global CDNs, instant cache invalidation, and simpler configuration. If you’re not locked into existing hosting, these are worth considering.
Netlify
Netlify connects directly to your GitHub repository and deploys on every push—no workflow file needed.
Setup:
- Go to netlify.com and sign up (free tier is generous)
- Click “Add new site” → “Import an existing project”
- Select GitHub and authorize access
- Choose your repository
- Configure build settings:
- Build command:
npm run build - Publish directory:
dist
- Build command:
- Click “Deploy site”
Netlify clones your repo, runs the build, and publishes the result. Your site gets a random subdomain like graceful-cupcake-123.netlify.app immediately.
Every push to main triggers a new deploy. You can see deploy logs, preview deploy previews for pull requests, and roll back to previous versions with one click.
Custom domain: Add it in Site settings → Domain management. Netlify provides DNS configuration instructions and provisions an SSL certificate automatically.
Vercel
Vercel offers similar functionality with even less configuration. It auto-detects Astro projects and configures everything.
Setup:
- Go to vercel.com and sign up
- Click “Add New” → “Project”
- Import your GitHub repository
- Vercel detects Astro and pre-fills settings
- Click “Deploy”
That’s it. Your site deploys to a .vercel.app subdomain with HTTPS and CDN distribution worldwide.
Vercel’s preview deployments are particularly good—every pull request gets its own URL so you can test changes before merging.
GitHub Pages
If you want to keep everything in GitHub’s ecosystem, GitHub Pages hosts static sites for free directly from your repository.
Setup:
Create .github/workflows/deploy.yml with this content:
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/deploy-pages@v4
id: deployment
Then enable Pages in your repository:
- Go to Settings → Pages
- Under “Source,” select “GitHub Actions”
- Push your workflow file
Your site deploys to yourusername.github.io/repository-name. For a cleaner URL, you can add a custom domain in the Pages settings.
Cloudflare Pages
Cloudflare Pages combines static hosting with Cloudflare’s global CDN network. Performance is excellent, and the free tier is generous.
Setup:
- Go to pages.cloudflare.com
- Connect your GitHub account
- Select your repository
- Configure:
- Build command:
npm run build - Build output directory:
dist
- Build command:
- Deploy
Cloudflare provides a .pages.dev subdomain. Adding a custom domain is straightforward if you use Cloudflare for DNS (and beneficial—you get their full CDN and security features).
Which Should You Choose?
| Platform | Best For |
|---|---|
| Netlify | General use, forms, functions, easy setup |
| Vercel | Framework-specific optimizations, preview deploys |
| GitHub Pages | Simplicity, keeping everything in GitHub |
| Cloudflare Pages | Performance, existing Cloudflare users |
| FTP (Chapter 14) | Existing hosting you’re already paying for |
All of them work well. If you’re starting fresh, pick one and go. You can always migrate later—your site is just static files.
Custom Domains
A site on graceful-cupcake-123.netlify.app works fine, but yourname.com looks professional. Connecting a custom domain involves updating DNS records to point at your hosting platform.
If You’re Using FTP Hosting
Your domain already points to your server—that’s how your WordPress site worked. Make sure the server-dir in your deployment workflow targets the same folder your domain is configured to serve. Usually that’s /public_html/ for main domains or /public_html/subdomain/ for subdomains.
If you’re moving from WordPress on the same host, your new static files replace the old WordPress installation. The domain keeps working without DNS changes.
Platform-Specific Setup
Each platform has a domain settings page. The process is similar everywhere:
Netlify:
- Site settings → Domain management → Add custom domain
- Enter your domain
- Follow DNS configuration instructions
Vercel:
- Project settings → Domains → Add
- Enter your domain
- Follow DNS configuration instructions
GitHub Pages:
- Repository settings → Pages → Custom domain
- Enter your domain
- Follow DNS configuration instructions
Cloudflare Pages:
- Project → Custom domains → Set up a custom domain
- Enter your domain
- If using Cloudflare DNS, it configures automatically
DNS Configuration
The platform will tell you what DNS records to create. You’ll make these changes at your domain registrar (GoDaddy, Namecheap, Google Domains, Cloudflare, wherever you bought the domain).
For apex domains (yourname.com without www):
Create an A record pointing to the platform’s IP addresses. Netlify uses 75.2.60.5, Vercel uses 76.76.21.21, and so on. The platform provides the current IPs.
Some registrars support ALIAS or ANAME records, which are better for apex domains because they can point to hostnames instead of IPs. Use these if available.
For subdomains (www.yourname.com, blog.yourname.com):
Create a CNAME record pointing to your platform URL:
- Netlify:
your-site-name.netlify.app - Vercel:
cname.vercel-dns.com - GitHub Pages:
yourusername.github.io
Example DNS setup for both apex and www:
| Type | Name | Value |
|---|---|---|
| A | @ | 75.2.60.5 |
| CNAME | www | your-site-name.netlify.app |
The @ symbol means the apex domain. This configuration points both yourname.com and www.yourname.com to your site.
Wait for Propagation
DNS changes take time to spread across the internet. Sometimes it’s minutes, sometimes up to 48 hours. Most changes propagate within an hour or two.
You can check propagation status at dnschecker.org—enter your domain and see which DNS servers have the new records.
While waiting, your old site might appear, or you might see SSL errors. Be patient. Once propagation completes, everything works.
SSL Certificates
All modern hosting platforms provision SSL certificates automatically once your domain points to them correctly. You don’t need to buy a certificate or configure anything.
After DNS propagates:
- Netlify, Vercel, and Cloudflare Pages issue Let’s Encrypt certificates automatically
- GitHub Pages provisions certificates within minutes of DNS verification
Your site will be available at both http:// and https://, with automatic redirection to HTTPS.
Verify Everything
Once your domain resolves to your new site:
- Visit
https://yourname.com—does it load with a valid certificate? - Visit
https://www.yourname.com—does it redirect or load correctly? - Visit
http://yourname.com—does it redirect to HTTPS? - Test a few pages and your contact form
- Check mobile
Your website is live on your own domain. Fast, secure, and deploying automatically every time you push.
What Comes Next
You have a website. It’s fast, it’s yours, and you built it by describing what you wanted.
That’s the core skill. Everything else is iteration.
Keep Going
Your site will grow. New pages, new sections, new ideas. The workflow stays the same: open Claude Code, describe the change, review the result, commit. Each session builds on everything that came before. Your DESIGN.md keeps the aesthetic consistent. Your CLAUDE.md keeps the conventions tight. The site accumulates intent, not technical debt.
Some things you might tackle next:
- A blog. If you migrated from WordPress, you already have one. If not, adding a blog is a single conversation: data file, list page, post template, RSS feed.
- Analytics. Drop in a lightweight tracker like Plausible or Umami. No cookies, no consent banners, just numbers.
- A contact form. Formspree or a similar service gives you form submissions without a backend. One
<form>tag with an action URL. - Performance tuning. Run Lighthouse, share the report with Claude Code, and ask it to fix whatever scores low. Image optimization, font loading, critical CSS—all straightforward when you can describe the problem.
- A second site. Now that you know the process, the next one goes faster. Copy the starterkit, swap in new content and a fresh
DESIGN.md, and you’re building again.
The Bigger Picture
Vibe coding isn’t about avoiding code. It’s about working at the level of intent. You think about what your site should do and how it should feel. The implementation follows from that.
This changes who can make websites. Not because the technology got simpler—Astro, TypeScript, and modern CSS are genuinely sophisticated tools. But because the barrier moved. You don’t need to learn the tools before you can use them. You describe the outcome, and the tools configure themselves.
Your site is proof. You made it. Ship it.