Successfully implemented URL-based routing for the YCode editor with a flexible and reusable abstraction that provides both convenience AND control.
const { routeType, resourceId, view, navigateToPage, navigateToCollection, updateView } = useEditorUrl();- Parses current URL state
- Provides individual navigation functions
- Used for edge cases (initial load, back/forward)
const { openPage, openCollection, openComponent } = useEditorActions();- Convenience methods - Update BOTH state + URL in one call
- Individual methods - Still available for edge cases
- Best of both worlds - DRY + Flexibility
/ycode - Base editor (no selection)
/ycode/pages/[id]?view=details - Page editing (general settings)
/ycode/pages/[id]?view=seo - Page SEO settings
/ycode/pages/[id]?view=code - Page custom code
/ycode/collections/[id]?view=items - Collection items view
/ycode/collections/[id]?view=fields - Collection fields management
/ycode/collections/[id]?view=settings - Collection settings
/ycode/components/[id] - Component editing
// In components - use convenience methods for user clicks
const { openPage, openCollection } = useEditorActions();
// Click a page → updates both state + URL
openPage(pageId);
// Click a collection → updates both state + URL
openCollection(collectionId, 'items');// Initial load from URL - state only, don't re-navigate
const { setCurrentPageId } = useEditorActions();
setCurrentPageId(pageId); // Updates state without pushing to router
// Browser back/forward - state only
setCurrentPageId(previousPageId); // Sync state without re-navigating// Switch tabs in settings panel - URL only
const { updateView } = useEditorUrl();
updateView('seo'); // Changes ?view=seo- ✅
LeftSidebarPages.tsx- UsesopenPage()for clicks - ✅
LeftSidebar.tsx- UsesopenCollection()for clicks - ✅
RightSidebar.tsx- UsesopenComponent()for component edit - ✅
PageSettingsPanel.tsx- UsesupdateView()for sub-tabs - ✅
app/ycode/page.tsx- Reads URL on mount, syncs state
- DRY Code - No duplicate navigation calls
- Flexibility - Can update state OR URL independently when needed
- Type Safety - TypeScript enforces correct view types
- Maintainable - Centralized routing logic
- Testable - Clear separation of concerns
✅ Click a page → URL changes to /ycode/pages/[id]
✅ Click a collection → URL changes to /ycode/collections/[id]?view=items
✅ Switch settings tab → Query param updates ?view=seo
✅ Refresh page → State restored from URL
✅ Browser back/forward → Navigation works correctly
✅ Delete page → Navigates to next page
✅ Create collection → Opens the new collection
✅ Component edit → URL changes to /ycode/components/[id]
- Deep linking to specific layers (e.g.,
?layer=layer-123) - Query params for zoom level
- History API for undo/redo URLs
- Collection view query params (items/fields/settings)
app/ycode/pages/[id]/page.tsxapp/ycode/collections/[id]/page.tsxapp/ycode/components/[id]/page.tsxhooks/use-editor-url.ts(withuseEditorActions)
app/ycode/page.tsxapp/ycode/components/LeftSidebarPages.tsxapp/ycode/components/LeftSidebar.tsxapp/ycode/components/RightSidebar.tsxapp/ycode/components/PageSettingsPanel.tsx
// Use convenience methods for user interactions
const { openPage } = useEditorActions();
openPage(pageId);// Avoid manually calling both - use convenience method
setCurrentPageId(pageId);
navigateToPage(pageId); // Redundant!// For URL sync without navigation (e.g., initial load)
const { setCurrentPageId } = useEditorActions();
setCurrentPageId(pageIdFromUrl); // State only