Centralized Page Title and Navigation System
Overview
The application uses a centralized configuration for page titles, descriptions, icons, and back button navigation. You no longer need to manually add <TWSetPageTitle> to every page!
How It Works
1. Centralized Configuration: config/routes.ts
All page metadata AND back button links are defined in one place:
export const routeConfigs: RouteConfig[] = [
{
path: "/company/dashboard",
title: "Dashboard",
description: "Company dashboard overview",
icon: "dashboard",
// No backLink = no back button
},
{
path: "/company/contacts/:id/view",
title: "View Contact",
description: "View contact details",
icon: "contacts",
backLink: "/company/contacts", // Back button goes here
pattern: /^\/company\/contacts\/[^/]+\/view$/,
},
{
path: "/company/contacts/:id",
title: "Edit Contact",
description: "Edit contact information",
icon: "contacts",
backLink: "parent", // Smart back to view page
pattern: /^\/company\/contacts\/[^/]+$/,
},
// ... more routes
]
2. Automatic Title Setting
ClientLayout.tsx automatically:
- Detects the current pathname
- Looks up the matching route config
- Sets the page title, description, and icon
- No history tracking needed!
No manual work needed on individual pages!
3. Hierarchical Back Button
TWNavHeader.tsx automatically:
- Gets current pathname
- Calls
resolveBackLink(pathname)from config - Shows back button based on route hierarchy
- Goes to configured destination (not browser history)
4. Dynamic Route Matching
For routes with IDs (like /company/contacts/[id]/view), use the pattern field:
{
path: "/company/contacts/:id/view",
title: "View Contact",
icon: "contacts",
backLink: "/company/contacts",
pattern: /^\/company\/contacts\/[^/]+\/view$/, // Matches any ID
}
The pattern RegEx matches dynamic segments:
[^/]+matches any characters except/(the ID)^and$ensure full path matching
Adding New Routes
Static Routes (No Dynamic Segments)
Simply add to config/routes.ts:
{
path: "/company/newpage",
title: "New Page",
description: "Description here",
icon: "dashboard",
backLink: "/company/dashboard", // Optional: where back button goes
}
Dynamic Routes (With IDs)
Add with a pattern and back link:
{
path: "/company/jobs/:id/edit",
title: "Edit Job",
description: "Edit job posting",
icon: "jobs",
backLink: "/company/jobs", // Static back link to list
pattern: /^\/company\/jobs\/[^/]+\/edit$/,
}
Pattern breakdown:
^\/company\/jobs\/- Exact start[^/]+- Match any ID (one or more non-slash characters)\/edit$- Exact end
Back Link Types
No back button:
{
path: "/company/contacts",
title: "Contacts",
icon: "contacts"
}
// No backLink property = no back button
Static back link (most common):
{
path: "/company/contacts/:id/view",
backLink: "/company/contacts", // Always go to this URL
pattern: /^\/company\/contacts\/[^/]+\/view$/,
}
Dynamic "parent" link (edit pages):
{
path: "/company/contacts/:id",
backLink: "parent", // Smart: go to /company/contacts/[same-id]/view
pattern: /^\/company\/contacts\/[^/]+$/,
}
When backLink: "parent" is used:
- Current:
/company/contacts/abc-123 - Back goes to:
/company/contacts/abc-123/view(adds/viewwith same ID)
Override for Special Cases
If a specific page needs a different title (not in the config), you can still use <TWSetPageTitle>:
<TWSetPageTitle
title="Custom Title"
description="Custom description"
icon="jobs"
/>
The manual override will take precedence over the centralized config.
Benefits
✅ Centralized - One place to manage all page metadata and navigation ✅ Automatic - No need to add components to every page ✅ Consistent - All pages follow the same pattern ✅ Maintainable - Easy to update titles and navigation across the app ✅ Type-safe - TypeScript ensures correct icon types ✅ Hierarchical back button - Predictable navigation based on page structure ✅ Works with bookmarks - Back button works even when visiting URLs directly
Migration Guide
Before (Manual on Every Page)
export default function ContactsPage() {
return (
<>
<TWSetPageTitle
title="Contacts"
description="Manage your contacts"
icon="contacts"
/>
<div>Page content...</div>
</>
)
}
After (Automatic)
export default function ContactsPage() {
// No TWSetPageTitle needed!
return <div>Page content...</div>
}
The title, description, icon, and back button are set automatically from config/routes.ts.
Files Modified
- config/routes.ts - Centralized configuration with
backLinksupport - lib/hooks/useAutoPageTitle.ts - Hook for automatic title setting (optional)
- components/layouts/ClientLayout.tsx - Auto-sets titles on pathname change
- components/ux/TWNavHeader.tsx - Uses
resolveBackLink()for back button - lib/types/pagestore.ts - Removed history tracking fields
- lib/pageStore.ts - Simplified without history tracking
Available Icon Types
From lib/types/pagestore.ts:
type IconType =
| "application"
| "back"
| "buzzfeed"
| "company"
| "connection"
| "contacts"
| "cvbuilder"
| "dashboard"
| "home"
| "invite"
| "jobs"
| "partner"
| "pipelines"
| "profile"
| "resume"
| "share"
| "talent"
| "talentpool"
| "timereport"
To add new icons, update lib/types/pagestore.ts and components/ux/TWNavHeader.tsx.
Testing
-
Navigate to any page in the app
- ✅ Title and icon should appear automatically
-
Navigate to a detail page (e.g.,
/company/contacts/abc-123/view)- ✅ Back button should appear
- ✅ Click back → goes to
/company/contacts
-
Navigate to an edit page (e.g.,
/company/contacts/abc-123)- ✅ Back button should appear
- ✅ Click back → goes to
/company/contacts/abc-123/view
-
Bookmark a detail page and visit directly
- ✅ Back button still appears with correct destination
All pages defined in config/routes.ts work automatically!
Related Documentation
BACK_BUTTON_WORKING.md- Detailed back button implementation (legacy doc, removed in repo cleanup)- config/routes.ts - Route configuration file