Skip to content

[pull] main from tldraw:main#440

Merged
pull[bot] merged 4 commits intocode:mainfrom
tldraw:main
Mar 11, 2026
Merged

[pull] main from tldraw:main#440
pull[bot] merged 4 commits intocode:mainfrom
tldraw:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Mar 11, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

ds300 and others added 4 commits March 11, 2026 10:30
…nload (#8200)

In order to ensure tldr downloads always reflect the latest state, this
PR changes `onDownloadTldr` to read directly from the durable object's
SQLite storage instead of fetching from R2. The R2 copy can lag behind
when a persist hasn't been triggered yet, whereas the SQLite storage is
the authoritative source of truth. Since the snapshot is fully loaded
into memory either way (the R2 path parsed via `.json()`), there's no
streaming advantage lost.

### Change type

- [x] `bugfix`

### Test plan

1. Open a tldraw file and make some edits
2. Immediately download the file as .tldr
3. Verify the downloaded file contains the latest edits

### Release notes

- Fixed tldr file downloads to always include the latest changes by
reading from the authoritative storage instead of the R2 cache.

### Code changes

| Section         | LOC change |
| --------------- | ---------- |
| Apps            | +3 / -6    |

Made with [Cursor](https://cursor.com)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk, small change isolated to the download path that only alters
the snapshot source from R2 to in-memory SQLite state. Main risk is
unexpected behavior if SQLite storage isn’t initialized or
`getSnapshot()` differs from the persisted R2 format.
> 
> **Overview**
> `.tldr` downloads (`onDownloadTldr`) now build the exported records
from the Durable Object’s live SQLite-backed storage (`getStorage()` +
`SQLiteSyncStorage.getSnapshot()`) instead of fetching/parsing the room
snapshot from R2.
> 
> This prevents downloads from lagging behind recent edits when
persistence to R2 hasn’t run yet, while keeping the rest of the export
flow (asset pruning and asset inlining) the same.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
681bb75. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…8038)

In order to show users a helpful error page instead of a blank white
screen when Clerk is down or rate-limited (429), this PR adds error
boundaries and a loading timeout to the Clerk authentication flow.

When Clerk is unavailable, `auth.isLoaded` stays `false` indefinitely
and tldraw.com renders a blank white page. This PR catches that case
with a 10-second timeout and also wraps the Clerk provider tree in error
boundaries.

### Change type

- [x] `bugfix`

### Test plan

1. Start `yarn dev-app`
2. Block Clerk's script loading (e.g. via DevTools network blocking for
`clerk.tldraw.com`)
3. Reload the page
4. After ~10 seconds, the error page appears with "Unable to connect"
and a "Refresh" button
5. Unblock Clerk and click "Refresh" — app loads normally

### Release notes

- Show an error page instead of a blank screen when the authentication
service is unavailable

### Code changes

| Section         | LOC change  |
| --------------- | ----------- |
| Apps            | +116 / -31  |
| Automated files | +27 / -0    |
#8199)

In order to fix ChatGPT copy-paste issues and improve the MCP app's
host-detection reliability, this PR refactors hostname resolution,
replaces the debug module with an integrated dev log panel, and adds
mobile platform handling.

Reimplemented from
[`max/fix-mcp-app-chatgpt-copy-paste`](https://github.com/tldraw/tldraw/tree/max/fix-mcp-app-chatgpt-copy-paste)
with a clean commit history.

### Change type

- [x] `improvement`

### Test plan

1. Run `yarn dev` in `apps/mcp-app` and connect from Cursor/Claude
Desktop — verify the canvas loads and tools work
2. Connect from ChatGPT via `yarn dev:tunnel` — verify host detection
resolves to `chatgpt`
3. Verify the dev log panel appears when `MCP_IS_DEV=true` and can be
toggled via the toolbar button
4. Verify fullscreen toggle works in desktop clients and is disabled on
mobile platforms

- [ ] Unit tests
- [ ] End to end tests

### Release notes

- Improve MCP app host detection for ChatGPT clients
- Add integrated dev log panel visible in dev mode
- Resolve host name client-side for more reliable detection
- Disable fullscreen on mobile platforms
- Clean up verbose server-side logging
- Update README with separate Claude Desktop local/remote setup
instructions

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes how host identity is resolved, what
bootstrap data is injected into the widget, and how
fullscreen/display-mode is handled (including new mobile restrictions),
which can impact client compatibility (ChatGPT/Claude/Cursor/VS Code).
No auth or data-storage model changes beyond logging/bootstrapping.
> 
> **Overview**
> Improves MCP host detection by splitting hostname resolution into
server-side (`resolveMcpAppHostNameFromServerInfo`) vs client-side
(`resolveMcpAppHostNameFromClientInfo`) parsing and broadening ChatGPT
detection; the widget now resolves host name from `app.getHostVersion()`
instead of relying on server-injected `hostName`.
> 
> Replaces the old ad-hoc widget `debug.ts` logging with an integrated
**dev log panel** gated by a new `isDev` bootstrap flag (injected by the
canvas resource) and a toolbar toggle.
> 
> Adjusts UI behavior for mobile hosts by disabling fullscreen
capability and forcing an exit from fullscreen if the host platform
becomes `mobile`, and removes verbose server-side `console.error`
checkpoint/debug logging. Adds an MIT `LICENSE.md`, updates the `README`
setup instructions, and enables `preview_urls` in `wrangler.toml`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
450b792. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…8202)

In order to prevent visual overflow (thick strokes, arrowheads, etc.)
from being clipped in exports while avoiding unnecessary whitespace,
this PR introduces an `'auto'` padding mode that renders with default
padding then trims to actual visual content bounds.

Clean reimplementation of
[`fix/export-visual-overflow`](https://github.com/tldraw/tldraw/tree/fix/export-visual-overflow).

### Change type

- [x] `improvement`

### Test plan

1. Export shapes with visual overflow (thick borders, arrowheads
extending beyond bounds)
2. Verify the export captures the full visual content without clipping
3. Verify no extra whitespace around the content
4. Test with explicit numeric padding — should behave as before (fixed
padding, no trimming)
5. Test frame exports — should still use frame bounds without padding

- [x] Unit tests
- [x] End to end tests

### API changes

- Changed `TLSvgExportOptions.padding` from `number` to `number |
'auto'`
- `'auto'` (default): renders with default padding, trims to visual
content
- `number`: fixed padding, no trimming (previous behavior with explicit
padding)
- Added `getSvgAsImageWithOptions` (internal) — returns `{ blob, width,
height }` instead of bare `Blob`
- Added `trimSvgToContent` (internal) — trims SVG viewBox to visual
content bounds

### Release notes

- Exports now automatically trim to visual content bounds, capturing
overflow (strokes, arrowheads) without extra whitespace
- The `padding` export option now accepts `'auto'` to enable this
behavior (default)

### Code changes

| Section         | LOC change  |
| --------------- | ----------- |
| Core code       | +354 / -30  |
| Tests           | +103 / -101 |
| Automated files | +3 / -1 (+ 44 binary snapshots) |
| Apps            | +3 / -3     |
| Config/tooling  | +1 / -0     |

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core export rendering and introduces a new `'auto'` padding
mode in the public `TLSvgExportOptions` API; incorrect trimming/cropping
could affect all exported PNG/JPEG/WebP/SVG outputs.
> 
> **Overview**
> Exports now support a new **`padding: 'auto'` mode** (and make it the
default behavior when `padding` isn’t a number) that renders with
default padding to capture visual overflow, then trims back to the
actual visual content bounds to avoid extra whitespace.
> 
> This threads a new `trimPadding` value through `getSvgJsx` →
`exportToSvg` → `Editor.getSvgElement/getSvgString` and updates
`Editor.toImage` to trim both raster exports (via a new internal
`getSvgAsImageWithOptions` canvas pipeline) and SVG exports (via a new
internal `trimSvgToContent` that adjusts the SVG viewBox/dimensions).
App export UI defaults were adjusted and the export calls now pass
`'auto'` when padding is toggled off; related unit tests were updated to
match the new bounds return shape and padding-applied signaling.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
880d9ec. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: huppy-bot[bot] <128400622+huppy-bot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@pull pull Bot locked and limited conversation to collaborators Mar 11, 2026
@pull pull Bot added the ⤵️ pull label Mar 11, 2026
@pull pull Bot merged commit 3494067 into code:main Mar 11, 2026
2 of 5 checks passed
@pull pull Bot had a problem deploying to deploy-staging March 11, 2026 15:13 Error
@pull pull Bot had a problem deploying to deploy-production March 11, 2026 15:13 Failure
@pull pull Bot had a problem deploying to deploy-staging March 11, 2026 15:13 Error
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants