Skip to content

Copy the page on the server when "+" adds one - #275

Merged
SunkenInTime merged 10 commits into
mainfrom
t3/page-add-copies-content
Oct 10, 2026
Merged

SunkenInTime merged 10 commits into
mainfrom
t3/page-add-copies-content

Conversation

@SunkenInTime

@SunkenInTime SunkenInTime commented Oct 10, 2026 •

Copy link
Copy Markdown
Owner

In local mode, "+" adds a copy of the page on screen. In the cloud it adds a blank page. This PR is the server half of fixing that: the server copies the page as it adds it.

What changes

  • The queued page.add op can carry an optional copyContentFromPagePublicId. When it does, the server copies that page's live items and lineups onto the new page in the same transaction that adds it. The new page never shows up without its content.
  • Copies get copy ids (<root>~cp1~<uuid>, from Keep items' roots when a cloud strategy is duplicated #273), so items glide from the page to its copy when the page turns.
  • A copy shows its source's pictures. A copied placed image names its original's picture (assetId, from Let an image show another image's picture #276), and lineup images keep their ids. Within a strategy nothing is copied or uploaded, so an image still uploading is copied too, and its copy shows the picture once the upload lands.
  • The copy is read and charged to a budget before anything is written. A page too large to copy (over 12 MiB) fails the add with the new code PAGE_TOO_LARGE_TO_COPY and leaves nothing behind.
  • Every page add in one batch draws on one shared budget. A batch is one transaction, so two large copies can't push it past Convex's limits, where it would fail on every retry. A copy past what's left fails on its own, without reading anything more.
  • If the page being copied is gone (deleted or in the trash) by the time the add lands, the page is added empty.
  • "Duplicate strategy" now copies through the same code (convex/lib/contentCopy.ts). A copy into another strategy brings each picture once, under the same id, sharing the stored bytes. Before, each copied placed image got a new picture id. It still refuses an image whose upload hasn't finished, and a lineup image shown on several pages is still charged to its budget once.

Compatibility

Checks

  • npx tsc --noEmit: clean.
  • npm run test:convex: 289 passing on the combined branch. New tests:
    • two copies in one batch share its budget;
    • a spent budget reads nothing more;
    • a shared lineup image is charged once;
    • copy ids, references, lineup agents and items;
    • a retried add copies once;
    • an image still uploading is copied and shows its picture once the upload lands;
    • a page gone before the add lands;
    • a too-large page is refused with nothing written.
  • Ground truth: deployed to dev, and pressed "+" in a web build while a new image's upload was held for 20 seconds. The new page and its copies were written in one transaction. The copied image names the uploading picture, and showed it during the hold and after the upload landed (see Copy the page when "+" is pressed on a cloud strategy #274).

Stacked on #273, with #276 merged in. Sync protocol change, so Dara looks first.

ci: convex contract analyze test

🤖 Generated with Claude Code

A queued page.add may name a page to copy. The server copies that
page's live items and lineups onto the new page, under copy ids that
keep their roots, in the same transaction that adds it, so the page
never appears without its content. A placed image still uploading is
left out; a page too large to copy refuses the add before anything is
written.

"Duplicate strategy" now copies through the same code (lib/contentCopy).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 45 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ea6afb24-de17-4d7f-ab84-fe1011b93410

📥 Commits

Reviewing files that changed from the base of the PR and between b7e88a6 and 7a0b54e.


⛔ Files ignored due to path filters (3)
  • convex/_generated/api.d.ts is excluded by !**/_generated/**
  • lib/collab/generated/convex_error_codes.dart is excluded by !**/generated/**
  • lib/collab/generated/convex_models.dart is excluded by !**/generated/**

📒 Files selected for processing (8)
  • convex/error_codes.json
  • convex/function_spec.json
  • convex/lib/contentCopy.ts
  • convex/lib/errors.ts
  • convex/lib/opTypes.ts
  • convex/ops.ts
  • convex/strategies.ts
  • convex/strategyDuplicate.test.ts

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

A batch is one transaction, so every page it copies now draws on one
budget: two large copies can no longer push the batch past Convex's
limits, where it would fail, and fail again on every retry. A lineup
image several pages show is charged to a copy once, as it is copied
once, so "Duplicate strategy" refuses no strategy it accepted before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SunkenInTime and others added 3 commits October 10, 2026 14:54
Copies in one batch share a budget. A copy after it is spent failed only
after reading a row, so many copies could still read past Convex's
limit. A spent budget now refuses before reading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A copied placed image now names its source's picture (assetId) rather
than getting a picture of its own. Within a strategy nothing is copied
or uploaded, so "+" no longer leaves out an image still uploading: the
copy shows the picture whenever the upload lands. A copy into another
strategy ("Duplicate strategy") brings each picture once, under the same
id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SunkenInTime
SunkenInTime changed the base branch from t3/duplicate-keeps-roots to main October 10, 2026 23:09
@SunkenInTime
SunkenInTime merged commit b726c94 into main Oct 10, 2026
14 checks passed
@SunkenInTime
SunkenInTime deleted the t3/page-add-copies-content branch October 10, 2026 23:56
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.

1 participant