PUBLIC PROJECT PATH FIX
Comprehensive documentation system guides
Public Project Path Extraction Fix
Date: October 29, 2025
Time: 1:00 PM PST
Status: 🐛 BUG FIX COMPLETE
Purpose: Fix project name extraction when switching to "public" project via project switcher
🚨 The Problem
When clicking "Public" in the project switcher, the application failed with:
❌ Project not found: english/undefined
📋 Available projects: ['english/public', ...]
Root Cause
The issue occurred in the navigateToProject method's path parsing logic:
Path building returns
/for public project:buildProjectPath('public', 'en') // Returns '/'Path parsing fails to extract project name from
/:const cleanPath = '/'.replace(/^\/+/, ''); // '' (empty string) const pathParts = ''.split('/').filter(Boolean); // [] (empty array) const projectName = pathParts[0]; // undefined ❌Project ID construction becomes invalid:
const projectId = `english/${undefined}`; // 'english/undefined' ❌
✅ The Solution
Added special handling for empty/root paths in the project name extraction logic:
// 🔧 FIX: Properly extract project name, handling language prefixes
// Examples:
// "/Ai-instructions" -> "Ai-instructions"
// "/es/Ai-instructions" -> "Ai-instructions"
// "Ai-instructions" -> "Ai-instructions"
// "/" -> "public" (root = public project)
// "/es" -> "public" (root with lang = public project)
const cleanPath = projectPath.replace(/^\/+/, ''); // Remove leading slashes
const pathParts = cleanPath.split('/').filter(Boolean); // Split and remove empty parts
// 🎯 EXTRACT PROJECT NAME with special handling for empty/root paths
let projectName: string;
if (pathParts.length === 0) {
// Empty path = public project (e.g., "/" -> "public")
projectName = 'public';
console.log(`🔍 Empty path detected, using: ${projectName}`);
} else if (pathParts.length === 1 && (pathParts[0] === 'es' || pathParts[0] === 'en')) {
// Just language code = public project (e.g., "/es" -> "public")
projectName = 'public';
console.log(`🔍 Language-only path detected, using: ${projectName}`);
} else if (pathParts[0] === 'es' || pathParts[0] === 'en') {
// Language prefix present, use second part (e.g., "/es/GoGrab-Space" -> "GoGrab-Space")
projectName = pathParts[1] || 'public';
console.log(`🔍 Language prefix detected, extracted project: ${projectName}`);
} else {
// No language prefix, use first part (e.g., "/GoGrab-Space" -> "GoGrab-Space")
projectName = pathParts[0];
console.log(`🔍 No language prefix, using first segment: ${projectName}`);
}
// Get current language
const currentLang = this.documentationService.currentLanguage();
const langKey: 'english' | 'spanish' = currentLang === 'es' ? 'spanish' : 'english';
// Construct project ID
const projectId = `${langKey}/${projectName}`;
console.log(`🔍 Path analysis: projectPath="${projectPath}", cleanPath="${cleanPath}", pathParts=[${pathParts.join(', ')}], projectName="${projectName}"`);
console.log(`🎯 Switching to project ID: ${projectId}`);
🎯 How It Works
Path Parsing Cases
| Input Path | Clean Path | Path Parts | Extracted Project | Project ID |
|---|---|---|---|---|
/ |
'' |
[] |
public |
english/public ✅ |
/es |
es |
['es'] |
public |
spanish/public ✅ |
/GoGrab-Space |
GoGrab-Space |
['GoGrab-Space'] |
GoGrab-Space |
english/GoGrab-Space ✅ |
/es/GoGrab-Space |
es/GoGrab-Space |
['es', 'GoGrab-Space'] |
GoGrab-Space |
spanish/GoGrab-Space ✅ |
/en/Ai-instructions |
en/Ai-instructions |
['en', 'Ai-instructions'] |
Ai-instructions |
english/Ai-instructions ✅ |
Logic Flow
graph TD
A[Start: projectPath] --> B[Remove leading slashes]
B --> C[Split into parts]
C --> D{Parts length?}
D -->|0| E[projectName = 'public']
D -->|1| F{Is language code?}
F -->|Yes| E
F -->|No| G[projectName = parts[0]]
D -->|>1| H{First part is lang?}
H -->|Yes| I[projectName = parts[1]]
H -->|No| G
E --> J[Build projectId]
G --> J
I --> J
J --> K[Lookup project]
📊 Testing Results
Before Fix
✅ Switching to "GoGrab-Space" → Works
✅ Switching to "Ai-instructions" → Works
❌ Switching to "public" → FAILS with "english/undefined"
After Fix
✅ Switching to "GoGrab-Space" → Works (english/GoGrab-Space)
✅ Switching to "Ai-instructions" → Works (english/Ai-instructions)
✅ Switching to "public" → Works (english/public) 🎉
✅ Switching to "public" (Spanish) → Works (spanish/public) 🎉
🛠️ Implementation Details
Files Modified
apps/docs-angular/src/app/shared/project-switcher/project-switcher.component.ts- Method:
navigateToProject()- Lines 650-689 - Added 4-case conditional logic for project name extraction
- Added detailed console logging for debugging
- Method:
Key Changes
Added Empty Path Handling
if (pathParts.length === 0) { projectName = 'public'; }Added Language-Only Path Handling
else if (pathParts.length === 1 && (pathParts[0] === 'es' || pathParts[0] === 'en')) { projectName = 'public'; }Enhanced Language Prefix Detection
else if (pathParts[0] === 'es' || pathParts[0] === 'en') { projectName = pathParts[1] || 'public'; // Fallback to public if no second part }Default Case
else { projectName = pathParts[0]; }
🔍 Why This Happened
The "public" project is special because:
- It represents the root documentation (
/) - It's accessible to all users
- Its path is built as
/(empty) rather than/public
This design decision makes sense for URLs (/ is cleaner than /public), but required special handling in the path parser.
💡 Alternative Approach Considered
We could have renamed the folder from public to something else (e.g., getting-started), but:
- ❌ Would break existing URLs
- ❌ Would require updating all references
- ❌ Doesn't solve the root issue (root path handling)
- ✅ Current fix is cleaner and more robust
✨ Summary
This fix ensures that switching to the "public" project works correctly by:
- ✅ Detecting empty/root paths (
/or/es) - ✅ Mapping them to the "public" project name
- ✅ Constructing correct project IDs (
english/public,spanish/public) - ✅ Maintaining backward compatibility with all other projects
Result: All projects, including "public", now switch correctly! 🎉