Redirect renamed project slugs to current page (#944)#1387
Merged
Conversation
Renaming a project changes its short_name (URL slug), which previously made the old /project/<old-slug>/ URL hard-404 — breaking external links and search-engine results. This surfaced in the #1142 SEO audit, where /project/mapoutloud/ and /project/mixed-ability-art/ sat in Google's "Not found (404)" bucket. Add a ProjectAlias model (retired slug -> Project). Project.save() captures the old slug as an alias on rename (and clears a reclaimed slug so it can't self-redirect); the project view 301-redirects a retired slug to the current canonical /project/<slug>/. clean() keeps the live-slug + alias namespace unique so a slug always resolves to one destination. A ProjectAliasInline lets editors see/add aliases, and the idempotent seed_project_aliases command (wired into docker-entrypoint.sh) backfills the historical renames done before auto-capture existed: mapoutloud->geovisally, mixed-ability-art-> artinsight, smarthomedhh->homesound. Tests: website/tests/test_project_aliases.py (13) covering auto-capture, 301 redirect, slug reclaim, namespace uniqueness, visibility, seed idempotency, and 404 on unknown slugs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Renaming a project changes its
short_name(the URL slug), which previously made the old/project/<old-slug>/URL hard-404 — breaking external links and search results. This came out of the #1142 SEO audit, where/project/mapoutloud/and/project/mixed-ability-art/were sitting in Google's "Not found (404)" bucket.This adds a former-slug → current-page 301 redirect system so renames no longer break URLs, and backfills the known historical renames. Closes #944.
How it works
ProjectAliasmodel (website/models/project_alias.py): maps a retired slug → itsProject.Project.save()): whenshort_namechanges, the old slug is recorded as an alias pointing at the project; a reclaimed slug clears its old alias so it can't self-redirect.website/views/project.py): on a slug miss, look up the alias and 301-redirect to the canonical singular/project/<slug>/. A live project always wins over an alias.clean()on both models): the combined live-slug + alias namespace stays unique, so a slug always resolves to exactly one destination.ProjectAliasInline): editors see auto-captured aliases and can add historical ones by hand.seed_project_aliases, wired intodocker-entrypoint.sh): idempotently backfills renames done before auto-capture existed:mapoutloud→geovisallymixed-ability-art→artinsightsmarthomedhh→homesoundTesting
website/tests/test_project_aliases.py(13 tests): auto-capture on rename, 301 redirect, slug reclaim (no loop), namespace uniqueness, visibility, seed idempotency, and 404 on unknown slugs.--settings=makeabilitylab.settings_test.Post-deploy verification
Once on
master→ test (then tag → prod), confirm:curl -sI .../project/mapoutloud/→301→/project/geovisally/curl -sI .../project/mixed-ability-art/→301→/project/artinsight/curl -sI .../project/smarthomedhh/→301→/project/homesound/Then re-run GSC "Validate Fix" on the Not found (404) group.
Notes
website/migrations/is gitignored; the entrypoint regenerates + the test suite builds from models).🤖 Generated with Claude Code