06-reference/research

substack ghost permalink redirect plan

2026-07-04·research-brief·source: deep-research

The concrete 301-redirect plan for Substack /p/ permalinks when Sanity Check migrates to Ghost

The question

What's the URL redirect plan for Substack /p/<slug> permalinks so existing inbound links don't 404 when Sanity Check migrates from Substack to Ghost? (Ghost docs note this is a manual step.) Deliver the concrete mechanics — slug mapping, 301 implementation options (Ghost redirects.yaml vs Cloudflare), and gotchas. Context: this protects existing SEO and inbound links; Sanity Check lives at sc.raydata.co and RDCO already runs Cloudflare, so a Cloudflare redirect layer is available alongside Ghost-native redirects.

What we already know (from the vault)

What the web says

Convergences and contradictions

Synthesis for RDCO

Primary recommendation: use Ghost-native redirects.yaml with the single official regex rule — if and only if Ghost is the confirmed host for sc.raydata.co. It is one rule, covers all 21 current posts plus every future imported post automatically, correctly preserves Ghost's own preview URLs via the UUID negative-lookahead, requires zero per-URL maintenance, and works on Ghost(Pro). This beats Cloudflare Bulk Redirects for the post archive because Bulk Redirects can't do regex — you'd hand-load 21 rows and re-load on every new import, for no benefit. The slug-mapping approach is therefore "preserve, don't remap": trust the importer's 1:1 slug carry-over and strip only the /p/ prefix, then spot-check.

Reserve Cloudflare for the edge cases the Ghost post-regex doesn't cover, since sc.raydata.co is already proxied through Cloudflare. Namely: (1) /feed/rss/ — Substack's RSS lives at /feed, Ghost's at /rss/, so feed-reader subscribers 404 without this; add it as a second line in redirects.yaml (/feed/: /rss/) or a Cloudflare rule. (2) Any apex/legacy path redirects (e.g. /archive). (3) The sanitycheck.substack.com subdomain URLs are unreachable from Ghost or Cloudflare — that host stays under Substack's control; keep the Substack publication alive (don't delete it) and set Substack's own "redirect to custom domain" so those links forward, or accept them as a bounded loss. Only inbound links pointing at sc.raydata.co/p/... are ours to 301.

If the destination turns out to be the existing Astro/Cloudflare Pages site (not Ghost), the equivalent mechanic is a Pages _redirects file with a placeholder rule: /p/:slug /:slug 301 (Pages supports :placeholder and :splat syntax). That is the Cloudflare-Pages-native analog of Ghost's regex and is the cleaner path than Bulk Redirects in that scenario, since it lives with the site build.

Ordered runbook (Ghost path):

  1. Run the Ghost Substack importer; confirm all 21 posts imported with slugs intact (open 2-3 posts, compare each Ghost slug to the old Substack /p/<slug>).
  2. In Ghost Admin → Settings → Labs, download the current redirects.yaml.
  3. Add the 301: block with the verbatim /p/-stripping regex above; add /feed/: /rss/ on a new line under the same 301: key. Spaces, not tabs.
  4. Re-upload redirects.yaml; it takes effect immediately.
  5. Test with curl -I https://sc.raydata.co/p/<a-real-old-slug> — expect 301Location: /<slug>200. Test /feed/rss/. Test one Ghost preview /p/<uuid> link still resolves (confirms the lookahead works).
  6. Keep the Substack publication live (don't delete) so substack.com-hosted links and image assets don't hard-break; set Substack's redirect-to-custom-domain option.
  7. Re-submit the Ghost sitemap in Google Search Console and watch Coverage for /p/ 404s over the next 2-4 weeks.

Open follow-ups

Related

Sources

Vault:

Web: