feat : share a game via a link - #97
Open
yluom wants to merge 1 commit into
Open
Conversation
Add a toolbar button that copies a link containing the current game, so a game can be shared without saving it anywhere. The PGN is compressed with lz-string into a `pgn` query param, which halves the link length compared to a plain percent-encoded PGN. Opening such a link loads the game through the existing url handling in `LoadGame`, next to `gameId` and `lichessGameId`, and reuses the existing `orientation` param. Clipboard feedback is factored into a `useCopyToClipboard` hook so that the share and the copy PGN buttons both acknowledge the copy.
This was referenced Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a share button to the analysis toolbar. It copies a link that contains the whole game, so a game can be shared without saving it or uploading it anywhere.
Opening the link restores the game (and the board orientation) on the analysis page.
This picks up the idea of #86 and rebases it on current
main.How
src/lib/shareGame.tsbuilds and reads the link. The PGN is compressed withlz-stringinto apgnquery param.LoadGame, in the sameuseEffectthat already handlesgameIdandlichessGameId, and reuses the existingorientationparam.useCopyToClipboardhook (the tooltip and icon confirm the copy for 2s). The existing Copy PGN button now uses it too, so both clipboard buttons behave the same way.Why compress
lz-string'scompressToEncodedURIComponentoutputs URL-safe characters directly, so there is no percent-escaping on top of it. On a 61-ply game:encodeURIComponent(pgn)compressToEncodedURIComponent(pgn)So a shared link is roughly half the size of one carrying a plain PGN, and it grows slowly since PGN text compresses well. No
@types/lz-stringis needed —lz-stringships its own typings.Notes
getGameToSave(game, board), the same helper as the save button, so a game played on the board gets proper headers before being shared.Tested
npm run lint(eslint +tsc --noEmit) andnpm run buildpass.?pgn=param is ignored without breaking the page.If the URL ever needs to be shorter
Compressing the PGN as text is the cheapest thing that works, and it keeps headers, comments and variations. For the record, here is what the alternatives cost. Sizes are for an 80-ply game; decode is timed in headless Chrome under
Emulation.setCPUThrottlingRateat ×8, roughly a mid-tier phone.loadPgnalone costs 4.9 ms there, which is the floor any scheme has to pay.loadPgnalready costs. Keeps headers and commentsCompressionStream('deflate-raw')lz-stringdependencyTwo dead ends I checked: deflating either binary stream makes it bigger (it is already near-uniform), and base64url's fixed 33% overhead can only be cut by ~5% with a URL-safe base85 alphabet.
If this ever needs to shrink,
from/tolooks like the sweet spot — the legal-move index is the true minimum but has the worst ratio. Happy to do either as a follow-up; I kept this PR to the simple version on purpose.