This document records the reorganization performed to properly separate the 2021 and 2025 versions of the OWASP Top 10 documentation into independent MkDocs sites while maintaining backward compatibility with existing URLs.
When the 2025 Release Candidate was being developed, the 2025 content was temporarily placed in /2021/docs/en/2025/ and the /2021/mkdocs.yml file was modified to include both 2021 and 2025 content in a single combined site. This created several issues:
- Confusing structure - The "2021" directory contained both 2021 and 2025 content
- Difficult maintenance - One mkdocs.yml file controlled both versions
- Unclear ownership - It wasn't clear which version was "primary"
- Messy navigation - The site showed both "Current Release" and "Release Candidate" sections
- Improper location - 2025 files belonged in
/2025/docs/en/, not in the 2021 directory
Reorganize the repository to:
- Move 2025 docs to their proper location (
/2025/docs/en/) - Create separate, independent MkDocs configurations for each version
- Build both sites separately and deploy them together
- Maintain backward compatibility with existing 2021 URLs using HTML redirects
All moved from /2021/docs/en/2025/ to /2025/docs/en/:
0x00_2025-Introduction.md0x01_2025-About_OWASP.md0x02_2025-What_are_Application_Security_Risks.md0x03_2025-Establishing_a_Modern_Application_Security_Program.mdA01_2025-Broken_Access_Control.mdA02_2025-Security_Misconfiguration.mdA03_2025-Software_Supply_Chain_Failures.mdA04_2025-Cryptographic_Failures.mdA05_2025-Injection.mdA06_2025-Insecure_Design.mdA07_2025-Authentication_Failures.mdA08_2025-Software_or_Data_Integrity_Failures.mdA09_2025-Logging_and_Alerting_Failures.mdA10_2025-Mishandling_of_Exceptional_Conditions.mdX01_2025-Next_Steps.md
- Images:
2025-algorithm-diagram.png,2025-mappings.pngmoved from/2021/docs/assets/to/2025/docs/assets/ - CSS:
RC-stylesheet.cssmoved from/2021/docs/assets/css/to/2025/docs/assets/css/ - Shared assets copied:
OWASP_Logo_Transp.png,TOP_10_logo_Final_Logo_Colour.pngcopied to/2025/docs/assets/
/2025/docs/en/index.md- Welcome page for 2025 version/REORGANIZATION-2025.md- This file
/scripts/build-all.sh- Orchestrates building both 2021 and 2025 sites/scripts/generate-redirects.sh- Creates HTML redirect pages for backward compatibility/scripts/index-redirect.html- Root redirect template (redirects/to/2021/en/)
-
/2021/mkdocs.yml
- Changed
site_namefrom "OWASP Top 10:2025 RC1" back to "OWASP Top 10:2021" - Changed
site_descriptionto "OWASP Top 10:2021" - Added
site_url: https://owasp.org/Top10/2021/ - Removed entire "Release Candidate" navigation section
- Simplified navigation to only include 2021 content
- Changed
-
/2025/mkdocs.yml
- Added
site_url: https://owasp.org/Top10/2025/ - Updated all navigation paths from
'2025/...'to'en/...' - Added
- Home: 'en/index.md'to navigation - Changed repo_url from development URL to production
- Added
- /Makefile
- Added
build-2021target - builds only 2021 site - Added
build-2025target - builds only 2025 site - Added
build-alltarget - builds both sites with redirects - Added
serve-2021target - serves 2021 site on port 8000 - Added
serve-2025target - serves 2025 site on port 8001 - Updated
publishtarget - now deploys both sites together - Kept
generateandservefor backward compatibility
- Added
/2021/
├── docs/
│ ├── en/
│ │ ├── A01_2021-*.md # 2021 content
│ │ ├── 2025/ # ← 2025 content wrongly here
│ │ │ ├── 0x00_2025-*.md
│ │ │ └── A01_2025-*.md
│ │ └── index.md
│ └── assets/
│ ├── 2025-*.png # ← 2025 assets wrongly here
│ └── css/RC-stylesheet.css # ← 2025 CSS wrongly here
└── mkdocs.yml # Combined 2021+2025 config
/2025/
├── docs/
│ ├── README.md
│ └── assets/
└── mkdocs.yml # Pointed to wrong paths
/2021/
├── docs/
│ ├── en/
│ │ ├── A01_2021-*.md # 2021 content only
│ │ └── index.md
│ └── assets/ # 2021 assets only
└── mkdocs.yml # 2021-only config
/2025/
├── docs/
│ ├── en/
│ │ ├── 0x00_2025-*.md # 2025 content
│ │ ├── A01_2025-*.md
│ │ └── index.md
│ └── assets/
│ ├── 2025-*.png # 2025 assets
│ └── css/RC-stylesheet.css # 2025 CSS
└── mkdocs.yml # 2025-only config
/scripts/
├── build-all.sh # Build orchestration
├── generate-redirects.sh # Redirect generation
└── index-redirect.html # Root redirect template
https://owasp.org/Top10/→ Redirects to 2021 (preserves existing links)https://owasp.org/Top10/2021/→ 2021 sitehttps://owasp.org/Top10/2025/→ 2025 site
The build system automatically generates HTML redirect pages to ensure old URLs continue to work:
Root-level page redirects:
/A00_2021_Introduction/→/Top10/2021/A00_2021_Introduction//A01_2021-Broken_Access_Control/→/Top10/2021/A01_2021-Broken_Access_Control/- All 2021 pages that were previously at the root now redirect to
/Top10/2021/
Language directory redirects:
/en/→/Top10/2021/(English is at root of 2021)/ar/→/Top10/2021/ar//de/→/Top10/2021/de//es/→/Top10/2021/es/- All 11 languages supported
Version-specific /en/ redirects:
/2021/en/→/Top10/2021/(English moved from subdirectory to root)/2021/en/A00_2021_Introduction/→/Top10/2021/A00_2021_Introduction//2025/en/→/Top10/2025/(English at root for 2025 too)/2025/en/A01_2025-Broken_Access_Control/→/Top10/2025/A01_2025-Broken_Access_Control/
All redirects are created by scripts/generate-redirects.sh during the build process and use absolute paths with /Top10/ prefix to work correctly when deployed to owasp.org/Top10/.
Language Selector Fix:
The extra.alternate section was removed from 2021/mkdocs.yml to allow the i18n plugin with material_alternate: true to automatically generate correct language selector links based on the site_url configuration. This ensures language links work correctly both locally and in production.
# Build only 2021
make build-2021
# Build only 2025
make build-2025
# Build and serve both versions together (port 8000)
make serve
# Serve individual versions with live-reload
make serve-2021 # Port 8000
make serve-2025 # Port 8001The make serve command builds both sites and serves them together using Python's HTTP server:
- http://localhost:8000/2021/ - 2021 version
- http://localhost:8000/2025/ - 2025 version
The individual serve-2021 and serve-2025 targets use MkDocs' live-reload feature for rapid development.
# Build both sites with redirects
make build-all
# Or use the script directly
./scripts/build-all.shThis creates:
build/2021/- Complete 2021 sitebuild/2025/- Complete 2025 sitebuild/index.html- Root redirect to 2021build/en/,build/ar/, etc. - HTML redirects for backward compatibility
# Deploy both sites to GitHub Pages
make publishThis:
- Runs
build-allto build both sites - Creates a git repository in the
build/directory - Force-pushes to the
gh-pagesbranch
After reorganization, verify:
-
make serve-2021starts 2021 site successfully -
make serve-2025starts 2025 site successfully - 2021 site shows only 2021 content (no 2025 references)
- 2025 site shows only 2025 content with RC watermark
- All images load correctly in both versions
- All 11 languages work in 2021 site
-
make build-allcompletes without errors - Generated redirects exist for all languages
- Root
index.htmlredirects to 2021 - After deployment, all three URLs work:
https://owasp.org/Top10/(root)https://owasp.org/Top10/2021/https://owasp.org/Top10/2025/
- Old 2021 URLs redirect properly
- No 404 errors on previously working links
Cause: Navigation references files that don't exist
Solution: Check that all paths in /2025/mkdocs.yml start with 'en/...' and files exist in /2025/docs/en/
Cause: Asset paths still reference ../../assets/
Solution: Paths should be ../assets/ in all 2025 markdown files
Cause: generate-redirects.sh not executed or build directory missing
Solution: Run ./scripts/build-all.sh which calls the redirect script
Cause: Git authentication or build errors Solution: Ensure SSH keys are configured for GitHub and build completes successfully
Cause: HTML redirects weren't generated or deployed
Solution: Verify build/en/, build/ar/, etc. directories contain index.html redirect files
- Create
/2028/directory with same structure as 2025 - Create
/2028/mkdocs.ymlwithsite_url: https://owasp.org/Top10/2028/ - Add
build-2028target to Makefile - Update
/scripts/build-all.shto include 2028 build - Update root redirect if needed (when 2028 becomes official release)
- Copy language directory from 2021 (e.g.,
/2021/docs/fr/→/2025/docs/fr/) - Translate markdown files
- Update
/2025/mkdocs.ymlto add language to i18n plugin configuration - Add nav_translations for the new language
- Remove
RC-stylesheet.cssreference from/2025/mkdocs.yml - Update
/scripts/index-redirect.htmlto redirect to 2025 instead of 2021 - Rebuild and redeploy
- Git history preserved: All 2025 files moved with
git mvto maintain history - Backward compatibility maintained: Existing 2021 URLs continue to work via redirects
- Clean separation: Each version has its own independent configuration and build
- Flexible deployment: Can build/serve versions independently or together
- Scalable: Pattern established for future versions (2028, 2031, etc.)
- Standard tools: Uses
mkdocs serveandmkdocs build- no custom tooling required
- CONTRIBUTING.md - Build process for maintainers
- Plan file - Original implementation plan