Payment confirmed
Setup fee cleared in Stripe. Nothing else on this list starts before this is checked.
From signed up to live, one owner per step
9 of 11 clients stuck for over a year never paid a cent, and 59 of 85 live clients have no owner recorded. Nothing below starts before payment, and every step has a name attached.
Setup fee cleared in Stripe. Nothing else on this list starts before this is checked.
One name recorded against the client record before any build work. This is the field that's empty on 59 of 85 live clients today.
Personal, Podcast, or Business (see Pricing), plus templated vs. custom theme.
Initial articles, About/Home/Contact copy gathered, site built and shared back for the client's review. Moving an existing site? Follow Site Migration.
Nameserver path (see Domains & DNS).
GSC, Plausible, and Bing all confirmed working (see the gate below), then send the Live Site template.
Moving an existing WordPress, Webflow or Substack site onto our platform
The goal is simple: the client loses no traffic. Every URL Google knows about either still works on the new site or 301-redirects to the right new page, and every post and photo comes across. Work the 9 steps in order. Each item has a short line under it saying why it matters.
One master sheet of old URLs, ranked by traffic and backlinks. Details ↓
Same slug, or a 301. Details ↓
Title, slug, body, original date, SEO fields. Details ↓
Full resolution, re-hosted on our media. Details ↓
Pages, nav, DNS & email, tracking, forms. Details ↓
Counts match, redirects work, nothing points to the old site. Details ↓
Content freeze, then switch the domain. Details ↓
Same day, then days 3, 14 and 30. Details ↓
Trello comment, client preferences, URL sheet saved. Details ↓
ash@nickgray.net as a Full user. GSC is the most important source: it shows which pages actually get clicks and links./sitemap.xml or /sitemap_index.xml).The full list of what the old site says it has./vs3-backlink-snapshot.Keeps a record of which URLs other sites link to..htaccess. Webflow: Site settings → Publishing → 301 redirects. Substack has none.old_url · type (post / page / category / tag / author / media / other) · GSC clicks · backlinks · new_url · action (same slug / 301 / drop) · migrated? · verified?. The top 20–50 rows get checked by hand after launch./{slug}/, not under /blog/. See How our URLs work below./2019/05/my-post/ or /p/my-post → /my-post. There are no wildcard rules, so it's one row per old URL. Use the platform cheat sheets below.new_url and action for every row.Anything with traffic or backlinks gets "same slug" or "301", never "drop".name.substack.com, we can't redirect it. Tell the client and have them link the new site from their Substack about page and last post. Also agree before cutover what happens to the newsletter.For every post, carry over:
For whoever runs the import: posts with images or quotes go in with pw create (Lexical upload nodes), because pw article publish rejects them. --publish-at schedules an import. After any pw patch, run pw deploy <slug>, because patching doesn't deploy on its own.
/wp-content/uploads/ (drop the -300x200 size endings). Webflow: the website-files CDN. Substack: substackcdn.com. Webflow images can vanish once the client cancels, so download them first./vs3-alt-text./seo-images or PageSpeed.This is the list that's easy to miss.
Site structure
SEO
extraJsonLd.robots.txt customisations./blog/x, /p/x, /2019/05/x links directly. Don't rely on redirects for our own links.Domain, DNS & email (where most migrations break)
pw dns, or the client's email stops working.pw domain add first, then send the nameserver pair it returns.Cloudflare can assign a different pair per domain, so never send a pair from memory. See Domains & DNS.Tracking & integrations
Facts
/fact-check on the bio, About page and any claims before the site goes live.new_url and an action.pw content-export <slug>.pw get redirects), and none lead to a 404 or chain through another redirect./vs3-migration-diff <slug>.It diffs the URLs, tests the redirects, checks that images load, and recovers images at risk.old.<domain>).It's the fallback and the image source if anything was missed. The client must not cancel it yet.Same day
verified? column./sitemap.xml lists the new URLs.In Search Console
Days 3, 14 and 30
/audit <slug>, then /vs3-seo-audit.CLAUDE.md at the root of their site-* repo.Plan every redirect around these rules.
| What | URL on our platform | Notes |
|---|---|---|
| Home | / | |
| Posts | /{slug}/ | At the root, not under /blog/. |
| Pages | /{slug}/ | Also at the root. If a page and a post share a slug, the page wins. |
| All posts | /blog/ | |
| Category | /category/{slug}/ | |
| Anything else | A redirect | Redirects collection in Payload. 301 by default. |
Redirects: matching ignores capitals and trailing slashes. Chains get flattened automatically and loops are rejected. Saving one rebuilds the site. The target can be a path or a full URL. No wildcards, so every old URL needs its own row. Use pw for everything, never raw REST or curl.
| Old URL | What to do |
|---|---|
| /my-post/ | Already matches. Same slug, no redirect. |
| /2019/05/my-post/ | Slug my-post + 301 from the dated path. |
| /blog/my-post/ | Same slug + 301 from /blog/my-post. |
| /category/x/ | Matches. Create the category with the same slug. |
| /tag/x/ | We have no tags. 301 to the closest category, or /blog/. |
| /author/name/ | 301 → /about/. |
| /page/2/ | Only if GSC shows traffic. 301 → /blog/. |
| /feed/ | 301 → our feed if the theme has one, otherwise /blog/. |
| /?p=123 | Ignore. Query strings can't be matched, and WordPress already pointed these at the real URL. |
| /wp-content/uploads/… | Only redirect images that rank or have backlinks (step 4). |
After import, ask Claude for /wp-migration-setup. Keep the old WordPress alive at old.<domain> during the transition.
| Old URL | What to do |
|---|---|
| /blog/my-post | Same slug + 301. The prefix might be /post/, /articles/, etc. One row per post. |
| /about, /contact | Same slug. |
| /blog | Matches our /blog/. Any other prefix (e.g. /articles) gets a 301 → /blog/. |
| /category/x | Create the category with the same slug, 301 if the path differs (e.g. /blog-categories/x). |
Images live on website-files.com and can disappear when the client cancels Webflow. Download everything first.
| Old URL | What to do |
|---|---|
| /p/my-post | Same slug + 301 from /p/my-post. |
| /archive | 301 → /blog/. |
| /about | Same slug. |
| /podcast, /s/{section} | Map to a page or category, then 301. |
Redirects only work if the Substack was on the client's own domain. Moving that domain disconnects it from Substack, so agree the newsletter plan first. Export the posts via Settings → Exports (posts come as HTML). The subscriber list stays with the client.
Copy → Paste → Send
Every client-facing template lives here, grouped by where it fires in the lifecycle. Hit Copy to grab the subject and body together.
Send once the domain is confirmed pointing to the new site: see Point to Nameservers below for how to get there.
SubjectYour site is live!
Hi [Name], The domain now lives under the site we've built! You can view it here → [site URL] Please disregard any email notification you might receive about a published article on your site while we finish polishing things up. If there's anything you'd like changed or updated, let us know and we'll work on it.
Always the default path. We pull the client's existing DNS into our system first, so nothing (especially email) breaks during the swap. See Domains & DNS for the Cloudflare backup.
SubjectPoint your domain to your new site
Hi [Name], Now that we've finalized the site and it's ready to go live, we need your help pointing your domain to the site we built. Please update the nameservers on your registrar (I believe that's [registrar, e.g. GoDaddy]) to these two: - nia.ns.cloudflare.com - vasilii.ns.cloudflare.com We've already pulled in your existing DNS records, so email and anything else pointed at the domain will keep working through the switch. If you need a hand, book a call with Pau here → https://cal.com/team-nick-pau/10min Thank you!
Client ending their PersonalWebsites.org service.
SubjectWe're sorry to see you go
Hi [Name],
Thank you so much for letting us know; it has been great working with you.
Are you planning to host the site on your end? If so, we're happy to keep hosting it for one more month for free so you have time to get set up and confirm the site is live on your end before switching nameservers/DNS. If not, we're happy to take the site down right away.
We've also attached the ZIP file containing all your posts, pages, and media. Please note that the themes are not included in the export.
If there's anything else you need help with, just let us know.
Blocked: Nick needs to confirm whether this is Hanz's or his to own before it gets written. See the open question on this page.
Never send a password in plain text over email. This template sends a reset link instead.
SubjectYour PersonalWebsites.org login
Hi [Name], Here's how to get into your site's backend: Login page: [admin URL] Email: [client email] We don't send passwords by email. Click "Forgot password" on the login page and it'll send you a reset link directly. Let us know if you get stuck.
Cadence is set by the client's tier: see Pricing (Basic is quarterly, Pro/Premium/Legacy are monthly or weekly).
SubjectBooking our check-in call
Hi [Name], Time for our regular check-in! Grab a slot that works for you here: [booking link] A few things to think about before we chat: - Any updates, wins, or new content ideas since we last spoke - Anything on the site you'd like changed See you soon!
Hi! Thanks for the call today. I enjoyed our chat. Please send me the following just like we discussed on the phone: I'll circle back once everything is completed.
Hi,
Just wanted to follow up as it looks like we missed each other on our scheduled call today.
I totally understand today might have gotten busy: it happens. At your earliest convenience, you can grab a new time that works best for you here:
[your booking link: see the Calendar Links in Resources]
Looking forward to chatting whenever it's convenient for you.
Buying, adding, transferring
DNS came up 59 times in two months, the loudest thing in the company. It's always the nameserver path. The Cloudflare account is a backup, not a second option to pick between.
Send these with the Point to Nameservers template. Before you send it, pull the client's existing DNS into our system first. That's what keeps their email and anything else on the domain alive during the switch.
nia.ns.cloudflare.comvasilii.ns.cloudflare.comnia.ns.cloudflare.com
vasilii.ns.cloudflare.comdig NS <domain>).Only when the nameserver swap stalls
We manage DNS directly on the client's behalf instead of waiting on them. This is a fallback, not a client-comfort judgment call. It isn't reached for by default.
Open setup guide →2026: VS3 Monthly Packages
Setup fees and monthly tiers by site type, pulled from the packages doc, plus where clients sign up.
One-time
Monthly plans
Best for: staying visible with minimal effort
Best for: original insights & growing SEO authority
Best for: full personal-brand content support
One-time
Monthly plans
Best for: staying visible with minimal effort
One-time
Monthly plans
| Code | Discount | Notes | |
|---|---|---|---|
| FRIENDS200OFF | $200 off | One-time, setup fee | |
| VIP200 | $200 off | One-time, setup fee | |
| FRIENDS300OFF | $300 off | One-time, setup fee | |
| FRIENDS100OFF | $100 off | One-time, setup fee | |
| CHERYLANN50 | $50 off | One-time, setup fee | |
| TOMGRUNDY50 | $50 off | One-time, setup fee |
Pulled from Stripe coupon screenshots in the doc: all fixed amounts off, applied once, against the one-time setup fee. Stripe's internal promo_… API IDs and live redemption counts are left off this page; check Stripe directly before relying on redemption limits.
Design library
12 themes in the catalog today, named below so this answers something on a client call. Custom builds are tracked in the CMS, not on this page.
siteType: custom plus excludeFromBulkRefresh), not a list on this page. Check the CMS, or run an audit, before quoting or touching a site as "custom."
Everything else
Backend access, calendar links, content rules, content topics, what's already automated, and the affiliate program.
These already run through Claude, so ask for them instead of redoing them by hand.
| Ask for | What happens |
|---|---|
| setup and audit <tenant> | Fills positioning fields, sets theme/nav/hero, then runs the full onboarding QA and fixes mechanical issues |
| add a custom domain | Connects, verifies, or removes a domain via Cloudflare, either nameserver or dns-records mode |
| audit <tenant> | Finds broken links/images, missing alt/OG/meta, migration junk, stale WP URLs |
| publish this article for <client> | Ingests a Google Doc, writes SEO metadata, uploads the hero image, publishes, verifies live |
| customize <tenant>'s hero/homepage | Hand-edits the tenant's Astro repo without breaking future theme refreshes |
| seo audit / seo check | Full-site or single-page SEO analysis with a prioritized fix list |
| blog audit / rewrite blog | Scores existing posts, replaces fabricated stats, fixes formatting and schema |
| fix hero photo on mobile | Reframes a cropped hero portrait per-tenant, survives theme refreshes |
Not the full list. There are 47 of these skills. Ask "what can you automate for X" if what you need isn't above.