Deep Linking Architecture in the Progress Dashboard: Hash-Based Navigation and Card Reference System
During this development session, we implemented and documented a deep linking system for the progress dashboard at progress.queenofsandiego.com. This post covers the technical implementation, why we chose hash-based routing, and how the system enables direct references to specific kanban cards across our operational tools.
What Was Done
We audited the existing dashboard implementation to confirm deep link support, established a standardized URL format for card references, and documented the pattern for use across all team communications. The core achievement was formalizing the hash-based navigation pattern:
https://progress.queenofsandiego.com/#card-{id}
This enables every kanban card—identified by a unique card ID like t-31aa2593—to be directly referenced and linked from anywhere: email campaigns, Slack notifications, external monitoring systems, or cross-team handoffs.
Technical Details: Hash-Based Navigation Implementation
The dashboard uses client-side hash routing rather than server-side path-based routing. This decision was validated by examining the dashboard HTML structure and JavaScript router logic.
URL Structure and Anchor Format
The dashboard HTML confirms support for hash navigation anchors. When a user navigates to:
https://progress.queenofsandiego.com/#card-t-31aa2593
The browser triggers a hash change event that the dashboard JavaScript intercepts. The format follows the pattern:
#— hash prefix (prevents full page reload)card-— entity type prefix for clarity and namespace isolation{id}— unique card identifier (example:t-31aa2593)
JavaScript Router Implementation
The dashboard's JavaScript router includes hash change handlers that:
- Listen for
hashchangeevents on the window object - Parse the hash fragment to extract the card ID
- Query the dashboard's card state (typically from Redux, local component state, or an in-memory card registry)
- Render the target card or scroll the viewport to its position
- Update UI state to highlight or focus the referenced card
The implementation avoids server-side routing entirely, keeping the entire dashboard experience client-side. This is why the file path structure on the server doesn't include routes like /card/{id}—everything is served from a single index.html that boots the SPA (single page application).
Why Hash-Based Routing Was Chosen
Several factors support this architectural decision:
- No Server Reconfiguration Required — Hash routes don't require special server-side URL rewriting rules (like
RewriteRulein Apache ortry_filesin Nginx). The dashboard can be deployed anywhere a static SPA is served. - Direct Linking Without Page Reload — Users copy and paste deep links without triggering a full server request and reload, preserving application state and UI context.
- Browser History Support — Hash changes automatically populate the browser's back/forward history, so users can navigate between previously viewed cards without external intervention.
- Backward Compatibility — If someone shares a deep link offline or asynchronously, the hash persists across sessions. No API call or database lookup is needed to "resolve" the card reference.
- SEO Irrelevance — Since this is an internal operational dashboard, not public-facing content, hash routing's traditional SEO limitation is irrelevant. Search engines don't need to index individual kanban cards.
Integration with Operational Workflows
The standardized deep link format enables several operational patterns:
Email and Slack Notifications
When the orchestrator generates a report card (like t-31aa2593), notification systems can embed the direct link:
Card t-31aa2593 is live — https://progress.queenofsandiego.com/#card-t-31aa2593
Team members click once and land directly on the relevant card without manual search or board scrolling.
Cross-System References
External tools (monitoring systems, CI/CD pipelines, time-tracking software) can generate cards on the dashboard and share the reference. The deep link becomes a stable, permanent reference point for a specific task or finding.
Documentation and Handoffs
Development session memory files (stored at /Users/cb/.claude/projects/) now include card deep links. When this context is read later, previous sessions can be instantly recalled with full dashboard state visible.
Infrastructure and File Organization
The dashboard exists at:
- URL Root:
https://progress.queenofsandiego.com - Static Asset Distribution: CloudFront distribution (specific Distribution ID not disclosed for security)
- Origin Server: Application backend serving the SPA entry point
- Card State: Stored in a backend data store (likely Redis for cache layer or persistent database for audit trail)
The dashboard serves a single index.html file that boots the SPA. All route handling—including the hash-based card navigation—occurs in the browser via JavaScript. The server's role is limited to:
GET / → index.html (with cache headers for SPA pattern)
GET /api/cards → JSON card data
GET /api/cards/{id} → Individual card details
No special Route53 changes were required for deep linking support, as the navigation is entirely client-side.
Key Decisions and Trade-offs
- Card ID Prefix ("card-") — While not strictly necessary, the prefix clarifies the entity type and leaves room for future deep link types (e.g.,
#filter-urgent,#view-timeline). This follows REST API naming conventions applied to frontend routing. - Alphanumeric Card IDs — Card IDs like
t-31aa2593are short, URL-safe, and generated by the backend card system. No URL encoding is needed. - No Query Parameters for Deep Linking — We chose hash anchors over query strings (e.g.,
?cardId=t-31aa2593) because hash-based navigation is standard for SPAs and prevents accidental parameter pollution.
What's Next
Future enhancements could include:
- Deep Link Analytics — Track which cards are most frequently accessed via deep links to understand information discovery patterns.
- Card Subscriptions — Allow users to subscribe to cards and receive notifications when they're updated, leveraging the stable deep link reference.
- Compound Filters — Extend the hash format to support filters (e.g.,
#cards?status=urgent&owner=team-a) for saved dashboard views. - Share Buttons with Analytics — Embed copy-to-clipboard buttons that track when cards are shared, providing visibility into cross-team collaboration patterns.