Swipefile is a 4,877-post library that Google and AI systems can fetch without trouble, but the page markup is missing the signals that make a library easy to trust, index, and cite: no structured data on any URL checked, no meta description on any post checked, no byline on the post template, and a catch-all route that answers every missing URL with HTTP 200.
Most of that is template work. A handful of changes to the Next.js templates cover most of the 4,995 URLs at once, and each one can be verified with a curl.
The content work behind it (thin older posts, one-sentence category hubs) has the larger upside and the larger uncertainty, and it should be driven by Search Console and Ahrefs data that only Neville has.
What was checked, in numbers
URLs in the sitemap
4,995
23 pages, 4,877 posts, 95 categories
raw/all-sitemap-urls.txt
Posts crawled, newest first
1,974
all HTTP 200
crawl/crawl.jsonl
Crawled posts with no meta description
1,856 of 1,856
the other 118 rows are the 23 pages and 95 categories
crawl/crawl.jsonl
Pages with any JSON-LD, Microdata, or RDFa
0
0 of 1,974 crawled, 0 of 23 templates
crawl/crawl.jsonl, raw/jsonld/
Stratified word-count sample
150 posts
newest, mid, oldest
crawl/rsc-wordcount-summary.json
Median body words, whole sample
138
sample, not the archive
crawl/rsc-wordcount-summary.json
Median body words, oldest / mid / newest 50
127 / 132 / 361
plain median of the rows; the summary script reports 365 for the newest bucket
crawl/rsc-wordcount-sample.json
Sample posts under 300 words
99 of 150
sample
crawl/rsc-wordcount-sample.json
Sample posts with a meta description
0 of 150
sample
crawl/rsc-wordcount-sample.json
Ahrefs Domain Rating
58
free endpoint, not Site Explorer
raw/ahrefs-dr.json
Phone Core Web Vitals, p75, latest 4 weeks
LCP 3,253 ms
INP 221 ms, CLS 0.0
raw/psi/crux-history-phone.json
Desktop Core Web Vitals, p75
LCP 2,255 ms
INP 68 ms, CLS 0.01
raw/psi/crux-history-desktop.json
The crawl stopped at 1,974 URLs on purpose. Every post uses the same template, and the 1,974 rows already agreed with the 23 hand-fetched templates on every structural fact. The word-count sample was drawn separately so that old posts are represented: 50 from the oldest sitemap file, 50 from the middle, 50 from the newest.
Data: every URL in the sitemap, a crawl of the 1,974 newest posts, a 150-post stratified word-count sample across the whole archive, 23 template pages fetched and 5 of them rendered in a headless browser, Chrome field data for 25 weeks, PageSpeed lab runs on 5 templates, and the free Ahrefs Domain Rating endpoint. No Search Console, GA4, or Ahrefs Site Explorer data was used.
Both screenshots are from 16 September 2026. The homepage HTML behind the desktop view is 695,495 bytes, of which about 361 KB is the card catalog serialized a second time as inline React Server Component data.
Do these first
Ranked by evidence strength and how many URLs each item touches. No time estimates. Owner is who has to touch it.
A
Template fixes
Each one is verifiable with a curl and covers most URLs at once.
1
Return a real 404 from the catch-all route
Every missing URL answers 200 today, so no tool can find the dead internal links.
/[...slug] returns 404 (or 410) in the first response, not a 200 with noindex. The existing noindex already keeps these out of the index, so this is a correctness fix, not an index-bloat emergency.
/random becomes a server-side 302 to a post. /secret returns 404 (or 401) for logged-out visitors. Do not pair noindex with a robots Disallow; a blocked page cannot show its noindex.
Check with GET, not only HEAD, on a cold and a warm request.
In the Next.js app, make the catch-all [...slug] route resolve the post before anything streams, and call notFound() when it does not exist, so the HTTP status is 404 and not a streamed 200. Add a redirect from /index.html to / in next.config with permanent: true. Verify in production with GET requests on a cold and a warm cache that an unknown slug returns 404 and that /llms.txt no longer returns the app shell.
2
Canonicals, redirects, and pagination
The definition page canonicalises to a URL that redirects back to it, and 19 sitemap pages have no canonical at all.
Touches 19 sitemap pages, both definition slugs, pagination on 96 listings
og:url equals the canonical on every page. Twelve inner pages point at the homepage today.
308 /page/1 to / and /category/{slug}/page/1 to /category/{slug}. Page 2 and later keep their own self-canonicals.
On /category/{slug}, make the next link go to /category/{slug}/page/2, not /page/2. Google ignores rel=next/prev as a hint; the fix is the crawl path the plain links create.
No page on the site carries structured data, so nothing ties the library to its author or its organisation.
Touches All 4,995 URLs
DevAgent
For the engineer
Shared layout: recommended/organization.jsonld and the WebSite node from recommended/website-searchaction.jsonld. WebSite supports the site name in Google results. SearchAction is optional; Google retired the sitelinks search box in November 2024, and the /search?q= page renders no results server-side today.
Post template: recommended/article.jsonld. Author must match a visible byline (item 4). recommended/breadcrumb.jsonld is optional; mobile results no longer show breadcrumbs.
Profile template: recommended/profilepage.jsonld and recommended/person-neville.jsonld.
Check with the Google Rich Results Test on one post. Use the Schema.org validator for ProfilePage and CollectionPage, which produce no rich result and are there for entity clarity.
What this buys: eligibility for Article rich results and a machine-readable entity graph. It is not by itself a ranking lift.
Agent prompt
Add a <script type="application/ld+json"> block to each Next.js template using the JSON in recommended/. Fill fields from the same data the page already renders (title, canonical URL, published date, share image, category, author profile). Render it in the server HTML, not in a client effect. Keep @id values stable: https://swipefile.com/#organization and https://swipefile.com/#website.
4
Visible byline on every post, and say who runs the site on About
The post template credits Swipebot. No human name appears on the page that a reader or a model can attach the work to.
Post template: a byline that names the real author or curator, with an accurate label ("Curated by", "Analysis by", or "Reviewed by"), linking to that person's profile. article:author and the same Person node in Article JSON-LD. Do not put a name on work that person did not write or review.
About: first paragraph says who runs Swipefile.com, links the profile, and states the site is free and curated. State the founding date only from a real record, not from the profile's Joined Aug 2017 line.
Keep "Analyzed by Swipebot" as a tool credit if wanted. Put a person first.
5
The definition paragraph
Nothing on the site says in one quotable sentence what Swipefile.com is.
One short self-contained paragraph: what Swipefile.com is, that it is free, who curates it, how many examples, how often it updates. Numbers inside the sentence, not in a widget.
Today no such paragraph exists anywhere on the site. It gives Google and AI systems something to quote for the brand query. No length guarantees a citation.
B
Content work
The larger upside and the larger uncertainty. Gated on Neville's data and reviewed by a person.
6
Content inventory and decisions, with data
The order of every content change depends on reports only Neville can open.
Touches The whole archive
Neville
For the engineer
Search Console page and query performance (full history, device and search-type splits including Image), the Pages indexing report, and Ahrefs page-level backlinks decide it. Top pages alone is not enough.
"No traffic, no links, short" is a review filter, not a deletion rule. Check impressions, image search, age, internal discovery, and unique value. Keep useful swipes. Improve pages with unmet demand. Consolidate real overlaps with redirects. noindex pages kept for users but not for search. 404 or 410 only for removed content with no replacement. Do not remove swipes to raise an average word count.
7
Upgrade posts by opportunity, not by age
The archive median is about 130 words on one repeated skeleton, and that is the largest content upside on the site.
Touches The older half of 4,877 posts over time
NevilleAgent
For the engineer
Do not pad, and do not swap one skeleton for a longer one. Add one self-contained paragraph a reader could quote alone: who made the ad and when if known, the persuasion device, why it plausibly works, any documented result. "Unknown" is allowed. An advertised price is not proof the ad performed. Keep the image and source link.
Order: posts with impressions but weak clicks, posts with links, posts in ranking decay (Search Console and Ahrefs, item 6). The oldest sitemap file (post-sitemap-5.xml, 877 URLs; the 50 oldest sampled at median 127 words) is the fallback order only where that data is missing.
Run a cohort first: 50 to 100 posts against comparable unchanged posts. Track impressions, clicks, and indexing before scaling. A bulk, unreviewed AI rewrite is the scaled-content pattern Google's guidelines warn about; human review of every batch is part of the job.
Set the real modified date when a post is rewritten so the visible "Updated on" line is true.
Agent prompt
For each URL in this CSV, read the live page and its source link. Draft one paragraph that names the advertiser and year if visible, the medium, the single persuasion device, why it plausibly works, and any documented number from the ad or its source. Write 'unknown' rather than guess. First sentence answers 'what is this swipe and why does it work'. Match the site's voice: direct, specific, no filler. Flag anything uncertain for review. Output url, draft_paragraph, uncertainties.
8
Category hub copy and taxonomy
95 hubs are the natural landing pages for example queries and each carries one sentence of its own text.
Touches 95 category pages
NevilleAgent
For the engineer
First check whether several hubs split one search intent (ads, outdoor-advertising, billboards; social, instagram, tweets). Merge before writing.
Then a real introduction per hub, sized to the topic: what the cluster is, when a marketer reaches for it, a few featured swipes with one sentence each on why, linked. Keep the H1 count and the grid.
Agent prompt
For each category URL, read the page and its first 20 posts. Draft an introduction: what this kind of marketing example is, when a marketer would use one, and three featured posts from the list with one sentence each on why. Link the three posts. No generic advice, no fixed length. Flag any category that overlaps another.
C
Cheap insurance
Template one-liners that remove a wrong signal rather than add a new one.
9
Meta description on every post
1,856 of 1,856 crawled posts have none, so Google writes every snippet from whatever text it finds first.
Touches 4,877 posts
DevAgent
For the engineer
This is snippet copy, not a ranking fix.
Template fallback: first analysis sentence plus advertiser and device. Programmatic is fine. Also emit og:description.
Hand-written descriptions only where Search Console shows impressions and weak click-through (item 6), and only later.
Agent prompt
Using site/swipefile-posts-crawled-1974.csv and the live page, write a unique meta description for each post in the list. Use the post title, first paragraph, and category. Name the advertiser or brand and the tactic. No stock call to action, no fixed length. Output a CSV with url, meta_description.
10
Sitemap hygiene
70 percent of posts share one batch lastmod, so the dates describe a migration and not an edit.
Touches The sitemap index and its six children
Dev
For the engineer
Keep one content record with real published and modified dates. Feed the visible date, Open Graph, JSON-LD, and sitemap lastmod from it. Where no trustworthy modified date exists, omit lastmod rather than invent one. 7 of 10 recent posts currently show lastmod before publish.
Do not batch-stamp lastmod on migrations. 3,410 of 4,877 posts share 7 or 8 November 2025; 109 share 27 to 28 August 2026.
Optional. Google's AI features do not use it. Serve as text/plain from public/ or a rewrite that bypasses the catch-all, or let item 1 return 404.
recommended/llms.txt is drafted from the live site structure. Its descriptive lines are draft copy for Neville to edit, not site text.
Which AI crawlers to allow for search, retrieval, and training is a business decision. Today all 14 tested crawlers get 200. A Content-Signal: line in robots.txt can state the policy; it is not a ranking lever.
Move "Command Palette" off the heading outline. One H1 in the delivered homepage HTML.
Descriptive alt text on post hero images.
48 pixel tap targets on mobile header buttons and post chips.
Fix the doubled /profiles title and add an intro line.
Watch for <title>X</title> on real posts on cache misses.
Label owned-product links on posts.
What already works
1Every missing URL returns HTTP 200
Fix first
The Next.js catch-all route answers unknown paths with a 200 status, no <title> in <head>, a noindex tag, and a canonical pointing at the missing URL itself.
Some SEO tools report the title of these pages as X. That is the <title> inside the X logo SVG in the footer, which every page carries. There is no page title.
Why it matters: Google calls this a soft 404. The noindex tag keeps these pages out of the index, so this is hygiene, not an emergency. The cost is elsewhere. Because everything is 200, no crawler or monitoring tool can find the dead internal links. Internal links already point at at least five dead slugs that get this treatment, for example /act-like-a-new-neighbor-not-a-brand and /olgivy-then-and-now-mission-statement. Any tool that trusts a 200 status (AI clients asking for /llms.txt, sitemap validators, uptime checks) is misled.
Two more routes share the pattern with no noindex at all. /random and /secret return a Next.js error shell (<html id="__next_error__">), no canonical, no robots tag, and they are linked from the site header. Both are indexable empty documents.
2Zero structured data on every URL checked
Fix first
This is entity and machine-readability work, not a ranking lever on its own. Article markup makes posts eligible for Article rich results. Organization and Person markup with sameAs is what ties the site to its author and social accounts for search engines and AI systems. The audit found no application/ld+json, no Microdata, and no RDFa on any of the 23 templates, the 5 Playwright renders, or the 1,974 crawled posts. Open Graph tags exist. They are not Schema.org.
Every cell is a JSON-LD type that belongs on a template. Every cell is empty.
The facts Schema.org needs are already on the page. A recent post, /ditch-the-generator-for-695-backup, shows a headline, a 1200 by 630 share image, article:published_time, a visible date, category chips, and a canonical. The profile at /profiles/nevmed shows a name, handle, join date, avatar, and five social links. Category pages show a count in the H1 and a description.
Drafts with live site values, no placeholders, are in recommended/.
3No post has a meta description
Template fix
1,856 of 1,856 crawled posts with a publish date have no meta description. 150 of 150 in the stratified sample have none. The PageSpeed SEO audit on the recent post fails on exactly this item, score 92, not 100. Category pages are mostly fine: 87 of 95 have one.
Crawled posts and category pages, by whether a meta description is present.
A meta description is snippet copy, not a ranking signal. Google writes its own snippet when the tag is missing and may rewrite one that exists. On a swipe page the first text it finds is often a category chip or the "Command Palette" heading. Posts also lack og:description, so shared links show only a title and image.
4The post template has no byline
Fix first
The default post template has no byline. The analyzer credit reads "Analyzed by Swipebot". The About page, /about, is 134 words and never says who runs the site. The person exists at /profiles/nevmed, but of 1,856 crawled posts only 152 link to any profile, and those are card links, not bylines.
The one page that does name Neville is the Friday SWIPES email, for example /the-swipes-email-friday-september-11st-2026, which opens "100% human written by Neville Medhora" and is the longest page in the sample at 1,058 words. That is the pattern the rest of the site lacks.
A recent post. Date, categories, and share image are all present. No person is named.
5The definition page fights itself, and 19 pages have no canonical
High
/what-is-a-swipe-file is the strongest content page on the site: 927 body words and a question H1. It is also the one page the sitemap and canonical get wrong. Its best block is the only one in the toolkit's 134 to 167 word target length, and it scored 60, still under the 70 citation-ready line.
The live page tells Google its canonical is a URL that redirects back to it. The sitemap lists the redirecting one. Pick the hyphenated URL, self-canonical it, and put that in the sitemap.
Nineteen sitemap URLs have no canonical tag at all: /tools, all nine tool pages, /profiles and the four profile pages, /popular/all, /popular/week, /popular/month, and /contact. Twelve inner pages set og:url to the homepage. And two pagination paths are indexable duplicates: /page/1 duplicates the homepage with its own self-canonical, and /category/images/page/1 duplicates the category page.
6In the sample, older posts run about 130 words on one skeleton
High, bulk work, data-gated
From the 150-post sample. The mid and oldest buckets are 100 posts; the three old posts read in full share one structure.
Every post in the sample, in 50-word bins. The shaded band is the toolkit heuristic, not a Google rule. Google states no preferred word count.Median body words by bucket: oldest 50 from post-sitemap-5.xml published around 2020, middle 50, newest 50 from 2026.
99 of 150 posts sit between 100 and 299 words. One post exceeds 1,000 words, and it is a newsletter. Old and middle posts share one structure: one or two sentences, an H2 "Why It Works" with four bullets, an H2 "Real-World Examples" with three names, then "Analyzed by Swipebot: Loading analysis...". Two live examples: /more-experiments-in-2024 (103 words) and /joseph-sugarman-slippery-slope (138 words).
Google's Search Quality Rater Guidelines have a section on scaled content: many pages with the same shape and little added value. The audit does not claim these pages are deindexed. It cannot see that without Search Console. It does say that thousands of URLs match that description.
Newer posts are better and still short. The BASE post at /ditch-the-generator-for-695-backup has unique H2s, real prices ($13k vs $695), and 253 rendered words. That format is the target for the archive, not a 1,500-word article.
795 category hubs carry one sentence of their own text
The hub's own text is the single line under the H1. Everything below it is card titles.
/category/images has an H1, one intro paragraph identical to its meta description, and a card grid. Playwright extracted 422 words, almost all of it card titles. The category sitemap lists 95 of these. They are the natural landing pages for "billboard examples" or "pricing page examples" queries and they have nothing to rank with beyond a title.
8Sitemap dates do not describe real edits
Medium
The sitemap is valid, split correctly, and HTTPS-only. The dates in it are not trustworthy, and Google only uses lastmod when it is consistently accurate.
One recent post. The sitemap says it changed before it was published. 7 of the 10 newest posts do this.The rest of the sitemap dates are batch stamps from rebuilds and migrations.
No post emits article:modified_time. 0 of 30 in a live sample, 0 of 1,974 in the crawl. Google has no on-page value to check lastmod against.
3,410 of 4,877 posts carry a lastmod of 7 or 8 November 2025, including 9 of the 10 oldest posts sampled, whose content is from 2020. Another 109 cluster on 27 and 28 August 2026.
21 of 23 page URLs share one rebuild stamp. 16 of 95 categories share a midnight stamp.
Chrome field data, 75th percentile, latest 4-week window.
Form factor
LCP
INP
CLS
Verdict
Phone
3,253 ms
221 ms
0.0
Does not pass. LCP and INP are in needs improvement, not poor, and neither was good in any of the 25 weeks.
Desktop
2,255 ms
68 ms
0.01
Passes. LCP and INP good in all 25 weeks. CLS sat in needs improvement (0.12 to 0.14) for four weeks in March and April and is 0.01 now.
Homepage URL, desktop
2,669 ms
74 ms
0.01 (all form factors)
The homepage alone misses the LCP threshold on desktop too.
25 weeks of phone field data from Chrome, 1 March to 12 September 2026. The shaded zone is the good threshold. The line never enters it.
Trust these over Lighthouse. Lab mobile LCP on the homepage was 12.2 seconds and that number is not what real visitors see. The lab run still names the causes.
PageSpeed lab scores on five templates.Uncompressed HTML in the first response. Brotli brings the homepage wire size down to about 44 KB (gzip would be about 86 KB), but the browser still parses all of it.About 361 KB of the homepage HTML is the card catalog serialized a second time.The delay is before the image request and after the download, not the download itself.
YouTube embeds: 2,483 KB and 1,081 ms of main-thread time on the homepage desktop run, 3,950 KB and 2,624 ms on the profile page.
GTM is preloaded in <head> and PostHog session recording loads on first parse on every sampled template.
The pricing calculator at /product-pricing-calculator loads a Leadpages embed that pulls Facebook, HubSpot, Mixpanel, and iubenda. Mobile lab score 29.
Homepage cards ship 1,164 by 1,351 pixel PNGs for a 750 pixel wide request, and post remix thumbnails waste 37 to 76 KB each at their 272 by 328 display size.
11AI search readiness
This section uses both toolkits. Where they agree, the finding is stated once.
Citability scores from citability_scorer.py. The homepage drops to 27.3 across all blocks because 16 of its 24 blocks are 20-word card captions. Post scores come from three URLs: a recent post, the 2017 Hathaway post, and /6-copywriting-formulas.
/llms.txt and /llms-full.txt return 200 with 217 KB of HTML and no title (section 1). An AI client that trusts the status ingests the app shell. llms.txt is optional and Google's AI features do not use it; the current state is still worse than either a real file or a 404. A draft is at recommended/llms.txt. Serve it as text/plain from outside the catch-all, or let the catch-all return 404.
No passage on any of seven scored pages reached the citation-ready threshold of 70 out of 100. The homepage is 24 blocks of 20-word card captions; 16 of them grade F. The best block on the site is "What to Put in Your Swipe File?" on the definition page, 158 words, score 60. The homepage's own claim "Trusted by 40,000+ users" sits in a widget, not in a sentence a model can quote.
No Wikipedia article or Wikidata item exists for Swipefile.com or for Neville Medhora. The concept article https://en.wikipedia.org/wiki/Swipe_file does not cite the site. Do not use it as an Organization sameAs; it describes the term, not the product. Do not write a promotional article either. The honest path is Organization and Person JSON-LD with sameAs to LinkedIn, YouTube (@kopywriting, about 140,000 subscribers at the time of the search), and X, plus a Wikidata item for the website once independent sources exist. The January 2026 Ahrefs podcast episode is one.
A request with Accept: text/markdown returns HTML. Not required today. Noted for later.
Platform readiness from the geo-seo-claude rubric.
9What Neville can check that this audit could not
Second opinion
The draft action plan was sent to ChatGPT (gpt-5.6-sol, xhigh effort) through the Codex CLI on 16 September 2026, with the report summary and the verified facts. Its headline objection: the priorities overvalue metadata and undervalue discovery, content usefulness, and mobile performance. Number of URLs touched measures implementation reach, not organic impact.
What the audit changed because of it
Softened the one-sentence thesis. Titles, headings, images, and links do carry meaning. The report now names the missing signals instead of claiming machine incomprehension.
Removed the fixed word targets (134 to 167, 140 to 160, 300 to 500 words). Google states no preferred length. The page now asks for one self-contained paragraph and a real introduction, and says the citation-band numbers are a toolkit heuristic. Google's content guidance
Reordered the post upgrade from oldest first to by opportunity first: pages with impressions, links, or decay, from Neville's own Search Console and Ahrefs. Oldest-first is the fallback only where that data is missing.
SearchAction dropped from the Google case; the sitelinks search box was retired in November 2024. WebSite stays for the site name. Rich Results Test replaced with the Schema.org validator for types with no rich result. Search box retirement
Deleted the claim that a definition paragraph moves every AI platform score. It is framed as a clarity fix. Google's AI guidance
The notFound() agent prompt now says to check existence before the response streams and to verify production GET status on cold and warm requests. Next.js documentation
Pagination: the report says Google ignores rel=next/prev; the fix is the crawl path the links create, not the tags. Google's pagination guidance
Phone Core Web Vitals now say does not pass, needs improvement, rather than fails.
Byline: the real author or curator, not Neville's name by default. Founding date is not inferred from a profile join date.
Explained the 1,974 versus 1,856 gap: 118 crawled rows are the 23 pages and 95 categories, which have no publish date.
Added to not checked and to what Neville can check: internal-link architecture (the crawler parsed an empty article node, so orphan data was discarded), image search performance, and a cohort test before scaling any content change.
Pruning: agreed. "Zero traffic, zero links, short" is a review filter, not a deletion rule. The plan says so.
Where the audit still disagrees
ChatGPT ranks content upgrades and hub curation above the template fixes. The audit keeps the template fixes (404 status, structured data, canonicals, meta fallback, byline) in Tier A because they are deterministic, verifiable, and cover every URL, and because Neville asked for a technical audit. The content work has the larger ceiling and the larger uncertainty. Both statements are on this page.
ChatGPT treats llms.txt as an optional experiment. The audit agrees it is optional, but the current state (HTTP 200 HTML shell with no title) is worse than either a real file or a 404, so fixing it stays on the list.
A separate fact-check pass then recomputed every number on this page from the raw crawl, sample, and API files before publication. Its corrections are already applied.
12Cleanup list
Small items, each with a file reference in findings/.
Security headers: only HSTS is set. Add X-Content-Type-Options: nosniff, Referrer-Policy, X-Frame-Options or a CSP frame-ancestors. Not a ranking factor.
Every sampled template injects an H2 "Command Palette" into the heading outline. Move it off a heading tag.
The homepage HTML contains its H1 twice. One copy is in the hidden RSC stream. Deliver one.
Every page carries a second <title> element inside the X logo SVG; some parsers read it as the page title.
Post hero image alt text is often the filename, for example ditch-the-generator-for-695-backup-e2cfc972.png.
Mobile header Search and menu buttons are 40 by 40 CSS pixels, below the 48 pixel tap target floor. Post category chips are 22 pixels tall.
/profiles has the title "Profiles | Swipefile | Swipefile" and no intro text before the cards.
On some renders the post <title> is streamed into the body after the hero image instead of <head>. The saved copy of /man-in-the-hathaway-shirt-tailoring-print-ad has no title in <head> and the real title 180 KB into the document; a live fetch later had it in <head>. Google reads a body <title>, but not every extractor does. Force blocking metadata on the post template.
IndexNow is not set up. Optional; Bing and a few other engines, not Google.
Promo links to kopywriting.com/join on posts carry no ownership or affiliate label next to the link.
14Scores, for reference only
How this was done
claude-seo plugin 2.3.1 scripts (fetch, render, parse, PageSpeed, CrUX history, screenshots, content quality) and the geo-seo-claude scripts (citability scorer, llms.txt validator, brand scanner), run by Grok subagents from a written specification, then cross-checked by the agent against raw files and live requests.
Crawl: 1,974 of 4,995 sitemap URLs, newest first, stopped when structural facts stopped changing. The crawl therefore covers 2025 and 2026 posts. Older posts are covered by the 150-post stratified sample and 30 sitemap-date checks.
Word counts come from the .prose node in the server HTML. Rendered words means Playwright extracted text, a different meter. The first <article> element on posts is empty and the body is in a second streamed copy, which is itself a finding (findings/content.md).
Not checked: Search Console, GA4, live rankings, live ChatGPT or Perplexity citation tests, the remaining 3,021 sitemap URLs, every /case/* page, HSTS preload status, image search performance. Internal-link architecture (orphans, click depth) was attempted and discarded: the crawler read the empty first <article> node, so its link graph is incomplete. That is a real gap for a library this size and needs a second crawl from the homepage.
The word-count sample is stratified by sitemap file (oldest, middle, newest). It supports "older posts are short" and does not measure the exact share of the archive under any threshold.
Nothing was deployed, submitted, or changed on swipefile.com.