Skip to content

Resolve author URLs the import filed under a different slug - #89

Merged
ssavutu merged 1 commit into
mainfrom
fix/author-slug-resolution
Aug 8, 2026
Merged

Resolve author URLs the import filed under a different slug#89
ssavutu merged 1 commit into
mainfrom
fix/author-slug-resolution

Conversation

@ssavutu

@ssavutu ssavutu commented Aug 8, 2026

Copy link
Copy Markdown
Member

The second half of the author work. #88 merged only its first commit — the category-archive redirects — so this carries the part that recovers real people, rebased onto main.

The defect

The import derives an author's slug from the WordPress login, and the logins don't agree with the names the site links by. Four distinct shapes are live in production:

URL that is linked slug the CMS holds why
ryan-keating rkeating abbreviated login
nayab-iqbal by-nayab-iqbal byline text used as the login
sanjana-bandi-2 sanjana-bandi WordPress duplicate-account suffix
stefan-kusmirek stefan-kusmirek-dev-thetriangle-org email used as the login

Ryan Keating has 59 articles and his author page was unreachable from every URL that names him. Seven authors are affected in total.

Why display-name matching

I started with pattern rules — strip a by- prefix, strip a -2 suffix — and they were wrong. rkeating and the email-derived slug fit no prefix rule, and the next import will invent a fifth shape.

The display name is the one thing all four have in common: the CMS holds the right name in every case, only the slug is wrong. Matching on it covers all four without enumerating them, and it keeps working after the ETL fix (DrexelTriangle/wordpress-etl#63) changes the slugs.

src/utils/authorIndex.ts builds the index from a paged /v1/authors sweep and caches it in process, on the taxonomyStore pattern already in the repo: same TTL-plus-stale-fallback, same single-flight dedupe, same refusal to cache an empty result — an index with no authors would answer "no such person" for everyone. 875 authors, ~114 KB.

getAllAuthors returns undefined if any page fails rather than a partial list, because a page that failed to load is indistinguishable from an author who does not exist.

Cost and safety

It runs only after the author lookup has already missed, so a page that resolves pays nothing. It returns null when the CMS can't be read, leaving the 404 in place rather than inventing a 301 during a blip that then caches.

The duplicate-suffix strip is limited to one or two digits: real CMS slugs carry a numeric id suffix to break collisions (erik-heyman-meltzer-870), and a broader rule would be one bad import away from resolving a URL to a different person.

Verification

astro check: 0 errors. Dev server against the live CMS, on this branch rebased onto current main:

/author/ryan-keating         301 → /author/rkeating
/author/nayab-iqbal          301 → /author/by-nayab-iqbal
/author/sanjana-bandi-2      301 → /author/sanjana-bandi
/author/stefan-kusmirek      301 → /author/stefan-kusmirek-dev-thetriangle-org

/author/rkeating                 200   (real slug, untouched)
/author/erik-heyman-meltzer-870  200   (real numeric-suffix slug, not stripped)
/author/crossword                301 → /crossword   (#88 behaviour, still intact)
/author/news                     301 → /news
/author/beeboop                  404   (genuinely unknown)

🤖 Generated with Claude Code

The import builds an author's slug from the WordPress login, and the logins do
not agree with the names the site links by. Four shapes are live:

  ryan-keating     -> rkeating                            abbreviated login
  nayab-iqbal      -> by-nayab-iqbal                      byline text as login
  sanjana-bandi-2  -> sanjana-bandi                       WordPress duplicate suffix
  stefan-kusmirek  -> stefan-kusmirek-dev-thetriangle-org email as login

Ryan Keating has 59 articles and his author page was unreachable from every
URL that names him. No pattern covers all four shapes and the next import will
invent a fifth, so match on the display name instead: the CMS holds the right
name in all four cases, only the slug is wrong. That also keeps working after
the ETL fix lands and the slugs change.

The index is built from a paged /v1/authors sweep and cached in process, on the
taxonomyStore pattern -- same TTL-plus-stale-fallback, same single-flight, same
refusal to cache an empty result, since an index with no authors would answer
"no such person" for everyone. 875 authors, about 114 KB.

It is consulted only after the author lookup has already missed, so a real
author's page costs nothing extra, and it returns null when the CMS could not
be read rather than inventing a redirect during a blip.

Verified against the live CMS: all seven recoverable slugs redirect to the
right person, rkeating/sanjana-bandi/erik-heyman-meltzer-870 still serve
directly, the section and subsection redirects still hold, and beeboop and
abuckingham -- WordPress handles the CMS has no record of -- still 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ssavutu
ssavutu merged commit 75d5bf4 into main Aug 8, 2026
1 check passed
@ssavutu
ssavutu deleted the fix/author-slug-resolution branch August 8, 2026 05:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant