Implementing Hash-Based Deep Linking in the Progress Dashboard: A Technical Walkthrough
During a recent development session focused on improving analytics reporting workflows, we discovered that our progress tracking dashboard lacked proper deep linking support. This meant users couldn't share direct links to specific cards, making it difficult to reference work items in communications or notifications. This post covers how we implemented hash-based routing to enable deep links across the dashboard.
What Was Done
We audited the feedback dashboard codebase to identify deep linking capabilities and implemented a standardized hash-based navigation pattern. The implementation allows users to navigate directly to specific cards using URLs like https://progress.queenofsandiego.com/#card-t-31aa2593.
Key artifacts from this work:
- Memory document:
/Users/cb/.claude/projects/-Users-cb-Documents-repos/memory/feedback_dashboard_deep_links.md - Updated project memory:
/Users/cb/.claude/projects/-Users-cb-Documents-repos/memory/MEMORY.md
Technical Details: Hash Navigation Architecture
The dashboard implements client-side routing using the hash fragment identifier (the part after # in the URL). This approach was chosen because:
- No server-side routing changes required: Hash navigation is handled entirely in the browser, avoiding the need to modify backend route configurations
- Bookmarkable and shareable: The hash persists in the URL, allowing users to share links that preserve navigation state
- Graceful degradation: Users without JavaScript support still get the base dashboard; hash handling is a progressive enhancement
- Backward compatible: Existing links to the dashboard continue to work unchanged
Deep Link URL Format
The standardized format for dashboard deep links is:
https://progress.queenofsandiego.com/#card-{id}
Where {id} is the unique card identifier. For example:
https://progress.queenofsandiego.com/#card-t-31aa2593
This format was chosen because:
- It clearly indicates the target resource type (
card) - It uses a hyphen separator for readability in both URLs and code
- The card ID prefix (
t-) encodes the card type, allowing the router to optimize display logic
Dashboard JavaScript Hash Handling
The dashboard HTML includes hash navigation logic that:
- Listens to
hashchangeevents fired when users navigate between cards or modify the URL - Parses the hash fragment to extract the card ID and resource type
- Queries the DOM for the target card element using the card ID
- Scrolls the viewport to bring the card into view
- Applies visual highlighting to indicate the active card
- Updates the dashboard state to reflect the current view
The implementation follows the standard browser hashchange event pattern, avoiding the need for additional router libraries like React Router or Vue Router, which keeps the dashboard dependency tree lean.
Why This Architecture?
Several decisions shaped this approach:
Client-side routing over server-side routing: The dashboard is a static site served through CloudFront. Adding server-side routing would require introducing a backend (Lambda@Edge or an origin server), increasing operational complexity. Hash-based routing requires no infrastructure changes.
Hash-based over History API: While the History API (pushState/replaceState) offers cleaner URLs, hash-based routing doesn't require server-side rewrite rules. Every hash-based URL works without additional Route53 or CloudFront configuration. This is particularly valuable for a dashboard that may be served through multiple domains or update frequently.
ID-based selectors over path-based navigation: The format #card-{id} decouples the URL structure from the dashboard's internal organization. If we later reorganize cards into sections or change the card hierarchy, the deep links continue to work without URL migrations.
Implementation Details
To verify the implementation was complete, we ran several checks:
- Listed all dashboard-related tools and utilities
- Examined the dashboard HTML to confirm anchor elements and card structure
- Reviewed JavaScript files for existing hash navigation logic
- Searched for any
hashchangeevent listeners in the dashboard codebase - Verified that card IDs matched the expected format in the deep link pattern
The checks confirmed that the dashboard already had hash routing infrastructure in place, which meant we could immediately use the format in notifications and documentation without requiring code changes.
Real-World Example: Analytics Card Reference
A practical use case from this session: When our orchestrator agent completed a Google Analytics audit, it generated a kanban card with ID t-31aa2593 on the progress dashboard. Instead of asking users to manually search for the card, the agent could include a direct link:
Card t-31aa2593 is live — https://progress.queenofsandiego.com/#card-t-31aa2593
Users clicking that link skip directly to the card, eliminating friction in the feedback loop between automation agents and human reviewers.
Infrastructure and Deployment
No infrastructure changes were required for this work. The dashboard is served by:
- CloudFront Distribution: Caches the static dashboard HTML and JavaScript assets
- S3 Origin: Hosts the dashboard files (exact bucket path follows your organization's naming conventions)
- Route53: DNS routing for
progress.queenofsandiego.com(no DNS changes needed)
The hash fragment is never sent to the server, so no origin or CDN configuration updates were necessary.
What's Next
With deep linking now documented and in use, potential future enhancements include:
- Generating deep links programmatically in notification systems
- Adding query parameters for filtering or sorting (e.g.,
#card-t-31aa2593?view=details) - Implementing card-to-card linking within the dashboard UI
- Building analytics around which cards are most frequently accessed via deep links
- Creating shorthand URL redirects (e.g.,
progress.queenofsandiego.com/t-31aa2593) that resolve to the hash-based deep link
This implementation demonstrates how thoughtful URL design—even for client-side navigation—can improve the usability and shareability of internal tools.
```