Add short URL sharing via paste service to fix URL truncation#188
Add short URL sharing via paste service to fix URL truncation#188GunitBindal wants to merge 2 commits intobacknotprop:mainfrom
Conversation
…k/messaging apps Share URLs for large plans can be 10-40KB+ because the entire plan + annotations are compressed into the URL hash. Services like Slack, WhatsApp, and Twitter truncate these URLs, making shared plans unviewable (related: backnotprop#142). This adds an optional paste-service backend that stores compressed payloads and returns short ~60-char URLs (e.g. share.plannotator.ai/p/aBcDeFgH). Changes: - Add Cloudflare Worker paste service (apps/paste-worker/) with KV storage and 90-day TTL for stored plans - Add createShortShareUrl() and loadFromPasteId() to sharing utils - Update useSharing hook to auto-generate short URLs with 1s debounce - Update ExportModal to show short URL as primary copy target with full hash URL as backup - Portal automatically supports /p/<id> paths via useSharing hook - Fully backward compatible: hash-based URLs continue to work unchanged - Graceful degradation: falls back to hash URLs if paste service is unavailable
- Worker: return only { id } so client constructs URL with its own
shareBaseUrl (fixes self-hosted deployments)
- importFromShareUrl: handle /p/<id> short URLs in addition to hash
URLs (fixes teammate import via short links)
- Anchor /p/<id> regex with ^ to prevent false matches on nested paths
- Pass shareBaseUrl to loadFromPasteId (was always defaulting)
- replaceState preserves base path instead of hardcoding /
- Clear stale shortShareUrl immediately on debounce to prevent showing
outdated link during the 1s delay
- Add shareBaseUrl to dependency arrays for loadFromHash and
importFromShareUrl callbacks
- Remove unused url field fallback from paste API response parsing
|
Thank you for this @GunitBindal Am I right in assuming that this is primarily intended for self-hosters? Also, do you self-host? Right now, the static site can be somewhat trusted because it's still open source and I'm not logging anything. There's no backend. This sorta changes the nature if I support this, but I understand why it's a great value add for the self-hoster especially. It doesn't mean I'm not opposed to adding it for the |
|
Hey Michael — thanks for the quick response! Also messaged you on X about this. To answer your question: no, I don't self-host — I use So while the PR is designed to also work for self-hosters, the primary motivation is fixing sharing on I totally understand the trust concern — the beauty of the current design is zero backend. A few ways to keep that trust while enabling short URLs:
I really love Plannotator — it's become essential to my Claude Code workflow, and this is the one thing blocking me from sharing reviews with my team daily. I'm happy to implement any of the above approaches if you point me in a direction. Also have a few more feature ideas — if you're open to receiving PRs, I'd love to contribute more. |
|
These are all great options - I think for large plans we can just be transparent that there will be a temporary storage of the plan to enable sharing on Plannotator.ai. I'll add this as I review the PR today. Your feature idea for remote sessions is good - happy to take contributions it's also something I've been wanting as I do remote sessions now too. |
Code reviewFound 1 issue:
plannotator/packages/ui/hooks/useSharing.ts Lines 116 to 118 in 0e32665 plannotator/packages/ui/hooks/useSharing.ts Lines 274 to 276 in 0e32665 plannotator/packages/ui/utils/sharing.ts Lines 299 to 306 in 0e32665 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
Summary
Fixes #187 — Share URLs for large plans are 10-40KB+ and get truncated by Slack, WhatsApp, email clients, etc., making the team sharing feature unusable for real-world plans. Also addresses the root cause behind #142 (silent fallback to demo plan on truncated URLs).
This adds an optional paste-service backend that stores compressed plan payloads and returns short ~50-char URLs like
share.plannotator.ai/p/aBcDeFgH.What changed
New:
apps/paste-worker/— Cloudflare Worker paste servicePOST /api/pastestores compressed plan data in KV, returns short IDGET /api/paste/:idretrieves stored dataModified:
packages/ui/utils/sharing.tscreateShortShareUrl()— POSTs compressed data to paste service (5s timeout)loadFromPasteId()— fetches plan by paste ID (10s timeout)toShareableImages(was module-private, now needed bycreateShortShareUrl)Modified:
packages/ui/hooks/useSharing.tsshortShareUrl,isGeneratingShortUrl,shortUrlErrorto hook stateloadFromHash()now checks for/p/<id>path pattern first, then falls back to hashModified:
packages/ui/components/ExportModal.tsxModified:
packages/editor/App.tsxuseSharingtoExportModalDesign decisions
PLANNOTATOR_PASTE_URLenv var overrides the paste API URLuseSharinghook detects/p/<id>paths, so the portal inherits short URL loading without any portal-specific changesDeployment note
The paste worker (
apps/paste-worker/) needs to be deployed separately topaste.plannotator.aiwith a Cloudflare KV namespace. Until deployed, the feature degrades gracefully — users see only the existing hash-based URL.Test plan
/p/<id>paths/#<hash>paths (backward compat)