Skip to content

Add human-readable, editable URLs for uploaded elevation routes - #73

Merged
aleexwong merged 2 commits into
mainfrom
claude/relaxed-goldberg-7ic539
Jul 25, 2026
Merged

Add human-readable, editable URLs for uploaded elevation routes#73
aleexwong merged 2 commits into
mainfrom
claude/relaxed-goldberg-7ic539

Conversation

@aleexwong

Copy link
Copy Markdown
Owner

Summary

Uploaded GPX routes now get pretty, shareable URLs that match the blog/race slug style, instead of an opaque Firebase doc id:

Before:  /elevationfinder/8Cf8rFpXCSSBuHg540wR
After:   /elevationfinder/boston-marathon-a3f9c

The slug is owner-editable from the dashboard; the trailing short id is the real resolution key, so renaming never breaks an existing link.

How it works

  • src/lib/routeSlug.ts (new) — slugify, generateShortId (6-char base36), buildRouteSlugPath, buildRouteUrl, extractShortId.
  • On upload, each route stores an editable slug (derived from the filename) plus an immutable shortId. The address bar and Share dialog use the pretty path.
  • Resolution (useRouteLoader): pretty {slug}-{shortId} URLs resolve on the trailing shortId via a Firestore query; the slug is cosmetic. URLs with no hyphen fall back to a direct doc lookup.
  • Backward compatible: Firestore auto-ids are hyphen-free 20-char strings, which cleanly distinguishes legacy /elevationfinder/{docId} links — they route to the direct-lookup fallback and keep working.
  • Dashboard editing: each uploaded route card gains an Edit URL button → modal with a live URL preview. The shortId is preserved (and minted for legacy routes on first edit), so shared links never break on rename.

Notes

  • No Firestore rules or index changes needed — gpx_uploads already allows public read (covers the shortId query), and single-field equality queries use the automatic index.
  • Existing uploads keep working on their old doc-id URLs and gain a pretty URL the first time their owner edits the slug.

Verification

  • tsc -b clean
  • Full npm run build clean (exit 0, all 80+ prerender routes generated)
  • Lint shows only pre-existing console/exhaustive-deps warnings
  • Slug helpers pass a runtime check (accents, junk input, length cap, legacy-id discrimination)

🤖 Generated with Claude Code


Generated by Claude Code

Uploaded GPX routes now get pretty, shareable URLs of the form
/elevationfinder/{slug}-{shortId} (e.g. /elevationfinder/boston-marathon-a3f9c)
instead of an opaque Firebase doc id, matching the blog/race slug style.

- New src/lib/routeSlug.ts: slugify, generateShortId, buildRouteSlugPath,
  buildRouteUrl, extractShortId helpers.
- Uploads store an editable `slug` plus an immutable base36 `shortId`; the
  address bar and share link use the pretty path.
- useRouteLoader resolves a URL param via the trailing shortId, falling back to
  a direct doc lookup so legacy /elevationfinder/{docId} links keep working
  (Firestore auto-ids are hyphen-free, which cleanly distinguishes the two).
- Owners can rename a route's URL from the dashboard route card; the shortId is
  preserved (and minted for legacy routes) so existing shared links never break.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013vrVKTbMjPPoeDcpzsPrR5
@netlify

netlify Bot commented Jun 24, 2026

Copy link
Copy Markdown

Deploy Preview for trainpace ready!

Name Link
🔨 Latest commit 2e5238a
🔍 Latest deploy log https://app.netlify.com/projects/trainpace/deploys/6a62fd7e65f09c0008f39f55
😎 Deploy Preview https://deploy-preview-73--trainpace.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 67
Accessibility: 89
Best Practices: 100
SEO: 100
PWA: 60
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
trainpace Ready Ready Preview, Comment Jul 24, 2026 5:52am

@codacy-production

codacy-production Bot commented Jun 24, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 33 high · 10 medium

Alerts:
⚠ 43 issues (≤ 0 issues of at least minor severity)

Results:
43 new issues

Category Results
UnusedCode 2 medium
BestPractice 4 medium
ErrorProne 2 medium
33 high
Complexity 2 medium

View in Codacy

🟢 Metrics 73 complexity · 3 duplication

Metric Results
Complexity 73
Duplication 3

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Brings in the fixed training-plan e2e spec (which now sets a valid race date
and asserts the Generate button is enabled before clicking, instead of
clicking it while disabled and timing out) so the e2e check passes.

Conflict in GpxUploader.tsx resolved by keeping main's proceedWithUpload()
refactor and threading this PR's shareable displayUrl through it, so both the
refactor and the pretty-URL feature are preserved. tsc -b passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KvvBmi4SLYYP7uL5ZJ1doK
@aleexwong
aleexwong merged commit d618bcf into main Jul 25, 2026
8 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants