Conversation
… route limit (#8291) Staging deploys to Vercel fail with: ``` Error: Builder returned invalid routes: should NOT be longer than 4096 characters ``` The `build.ts` script uses `regexgen` to create a trie-regex enumerating every asset filename for the immutable cache-control route. The Vite build now produces ~157 files, pushing this regex well over Vercel's 4096-char-per-route limit. **When it started failing:** `feat(mermaid): add @tldraw/mermaid package` (#8194) — merged Mar 18. Last successful deploy was #8273. **Root cause:** `regexgen` builds a trie-regex from all asset filenames. The exact-match approach was introduced in #4863 to prevent Cloudflare from caching 404 responses for `/assets/*` with immutable headers, which caused "Failed to fetch dynamically imported module" errors after deploys. **Fix:** Replace the per-file trie regex with an extension-based pattern. Given 3 example assets: ``` assets/admin-D_Yk9J1y.js assets/styles-BKwyi6c.css assets/Inter-Medium-abc123.woff2 ``` Old regex (regexgen): `^\/assets\/(?:admin\-D_Yk9J1y\.js|styles\-BKwyi6c\.css|Inter\-Medium\-abc123\.woff2)$` New regex: `^\/assets\/.+\.(js|css|woff2)$` | Request | Old regex | New regex | |---|---|---| | `/assets/admin-D_Yk9J1y.js` | Match (immutable cache) | Match (immutable cache) | | `/assets/styles-BKwyi6c.css` | Match (immutable cache) | Match (immutable cache) | | `/assets/nonexistent.js` | No match (no cache headers) | Match (immutable cache on 404) | | `/assets/foo` | No match | No match | ### Possible cons - **Slightly broader matching** — a request like `/assets/nonexistent.js` would get immutable headers on its 404 response. This could cause Cloudflare to cache the 404 at the edge, which was the original concern in #4863. - **Not an exact match** — we lose the guarantee that only known files get immutable caching. ### Why the cons don't matter in practice 1. Asset URLs come from compiled JS bundles referencing real content-hashed filenames — no user or browser crafts random `/assets/*.js` URLs 2. `coalesceWithPreviousAssets()` copies 30 days of old assets into every deploy, so old URLs from stale tabs don't 404 3. The old exact-match regex only enumerated the *current* build's assets — it never protected against old assets from previous builds returning 404 either. For stale tabs >30 days old, both approaches fail identically. 4. Even if Cloudflare caches a 404 with immutable headers for a fabricated URL, it only affects that specific fake URL — real asset URLs with content hashes are unaffected Also removes `regexgen` and `@types/regexgen` dependencies. Closes #8286 ### Change type - [x] `bugfix` ### Test plan 1. Deploy to Vercel staging and verify the deploy succeeds 2. Verify assets are served with `Cache-Control: public, max-age=31536000, immutable` 3. Verify non-existent asset paths without valid extensions don't get cache headers ### Release notes - Fix Vercel deploy failure caused by asset cache route regex exceeding 4096-char limit ### Code changes | Section | LOC change | | -------------- | ---------- | | Apps | +10 / -5 | | Config/tooling | +33 / -39 |
In order to get improved auth token refresh (updateAuth over existing WebSocket instead of full reconnect), this PR upgrades @rocicorp/zero from 0.25.9 to 0.26.1. Zero 0.26 breaking changes (neither affects us): - Custom headers to query/mutate endpoints now need allowlisting — we don't send any - WebSocket messages capped at 10MB — our mutations are nowhere near that The token refresh in `TldrawApp.ts` now benefits from Zero sending an `updateAuth` message without dropping the connection, fixing the reconnect every ~50s. ### Change type - [x] `improvement` ### Test plan 1. Open tldraw.com, sign in 2. Verify Zero sync works (create/edit documents) 3. Wait >60s, confirm no connection drops in devtools network tab ### Release notes - Upgrade Zero to 0.26.1 for smoother auth token refresh (no more periodic reconnects) ### Code changes | Section | LOC change | | -------------- | ------------ | | Apps | +2 / -3 | | Config/tooling | +309 / -21 |
In order to make local commits less painful when only a subset of packages change, this PR narrows what the Husky pre-commit hook runs: `yarn install` only when a `package.json` is staged, `build-api` only for packages with staged changes (via lazy filters), `build-i18n` only when `apps/dotcom/client` files are staged, and `refresh-assets` can be skipped when invoked from that filtered `build-api` path if nothing relevant to assets changed. A few verbose `typecheck` script logs were also trimmed. Personally I often ended up committing with \`--no-verify\` because the hook could take long enough that skipping checks felt worth the risk. On this machine a typical commit now finishes in about **~7s** instead of sometimes **~25s**. ### Change type - [x] `other` ### Test plan 1. Stage a change under a single package (e.g. `packages/editor`) and commit; confirm only that package’s `build-api` runs (and API reports re-staged as needed). 2. Stage a change with no `packages/*` API impact; confirm `build-api` is skipped when appropriate. 3. Stage only non-dotcom files; confirm `build-i18n` does not run. 4. Stage a `package.json` change; confirm `yarn install --immutable` runs. - [ ] Unit tests - [ ] End to end tests --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In order to stay current with the Vite ecosystem and benefit from the new OXC transpiler and Rolldown bundler, this PR upgrades Vite from v7 to v8 across all apps and templates. See the [Vite 8 announcement](https://vite.dev/blog/announcing-vite-8) for full details on what changed. ### Performance | App | Before | After | | --- | ------ | ----- | | examples build | 18s | 2s | | dotcom build | 19s | 3s | ### Migration changes - **`esbuild` → `oxc`**: Vite 8 replaces esbuild with OXC for transpilation - **`rollupOptions` → `rolldownOptions`**: Vite 8 uses Rolldown instead of Rollup - **Removed `esbuildOptions`** from `optimizeDeps` (no longer applicable) - **Dotcom: `plugin-react-swc` → `plugin-react`** (v6, Oxc-based in Vite 8) and `@swc/plugin-formatjs` → `@formatjs/unplugin` (framework-agnostic unplugin) - **`experimentalDecorators: true`** added to tsconfig base — Oxc does not yet support lowering native Stage 3 decorators, so we use legacy TypeScript decorators which Oxc handles natively ### Known issues Several plugins don't yet declare Vite 8 peer dependency support: - `@cloudflare/vite-plugin` (`^6.1.0 || ^7.0.0`) - `@vitejs/plugin-react` (`^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0`) - `@vitejs/plugin-vue` (`^5.0.0 || ^6.0.1`) These work at runtime but produce yarn peer dependency warnings. ### Change type - [x] `other` ### Test plan 1. Run `yarn dev` and verify the examples app loads 2. Run `yarn dev-app` and verify dotcom loads 3. Run `yarn build` and verify all packages build 4. Run tests across workspaces 5. Verify Cloudflare workers still deploy (vite-plugin peer dep) - [x] Unit tests - [x] End to end tests ### Code changes | Section | LOC change | | ------- | ---------- | | Core code | +2 / -2 | | Apps | +44 / -52 | | Templates | +52 / -89 | | Config/tooling | +1334 / -1053 | ### Release notes - Upgrade Vite from v7 to v8
) #8258 migrated from prettier/eslint to oxfmt/oxlint but missed updating `internal/scripts/lib/file.ts`, which still imported `prettier`. Since prettier was removed from devDependencies, `yarn workspaces focus` on Vercel (for analytics deploy) [crashes during postinstall](https://vercel.com/tldraw/analytics/6pQnhddPB1iQUS31h8NyWTBhHS2f) when `refresh-assets` tries to import prettier. This PR replaces the prettier import with oxfmt's `format()` function and uses `JSON.stringify` for JSON formatting (oxfmt is JS/TS focused). Relates to #8258 ### Change type - [x] `bugfix` ### Test plan 1. `yarn refresh-assets` succeeds 2. `yarn typecheck` passes 3. Clone repo to `/tmp`, run `yarn workspaces focus @tldraw/analytics @tldraw/monorepo config` — postinstall completes without "Cannot find module 'prettier'" error ### Code changes | Section | LOC change | | -------------- | ---------- | | Config/tooling | +8 / -16 | | Automated files | +36 / -36 |
This workflow is no longer used, so this PR removes it. ### Change type - [x] `other` ### Test plan - [x] N/A — just deleting an unused workflow file
Adds in support for mind maps as a new diagram type in mermaid. <img width="456" height="301" alt="Screenshot 2026-03-19 at 15 10 12" src="https://github.com/user-attachments/assets/e5cfe2b7-5174-4275-a5df-501883f3b278" /> <img width="1173" height="413" alt="Screenshot 2026-03-19 at 15 10 20" src="https://github.com/user-attachments/assets/21e17731-dabb-4230-a8b3-bba12eb28ee9" /> ### Change type - [ ] `bugfix` - [ ] `improvement` - [x] `feature` - [ ] `api` - [ ] `other` ### Test plan 1. Run the Mermaid diagrams example and compare the 20 mind map shapes vs the generated SVGs 2. Enable copy/paste handling for Mermaid code and try pasting in: ``` mindmap root((My Project)) Planning Goals Timeline Budget Development Frontend UI Design Components Backend API Database Marketing Social Media SEO Ads Launch Testing Deployment Feedback ``` ### Release notes - Adds mind map shape support to the @tldraw/mermaid package --------- Co-authored-by: Guillaume <guillaume@tldraw.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Guillaume Richard <mynameiskaneel@proton.me>
When two pushes to `main` happen in quick succession, the `publish-editor-extensions` workflow fails with "already exists". The concurrency group serializes job execution, but the marketplace API has propagation delay — both runs fetch the same stale version and compute the same next version. This PR wraps the version-bump → package → publish cycle in a retry loop. If `vsce publish` fails with "already exists", the script waits 60s, re-fetches the marketplace version, re-computes the next version, re-packages, and retries (up to 5 attempts). Also moves the `vsce show` marketplace fetch (previously a separate workflow step) into the script so it can be re-run on retry. ### Change type - [x] `bugfix` ### Test plan 1. Review the retry logic in `publish-editor-extensions.ts` 2. Verify the "already exists" error string matches what vsce actually outputs (confirmed from CI logs: `::error::tldraw-org.tldraw-vscode v2.216.1 already exists.`) - [ ] Unit tests - [ ] End to end tests ### Code changes | Section | LOC change | | -------------- | ---------- | | Config/tooling | +52 / -27 |
…rs (#8280) Sentry shows multiple transient Cloudflare R2 errors (`internal error (10001)`, `connectivity issue`, `network connection lost`, `unspecified error (0)`) and service binding errors (`proxy request failed`) in the tldrawusercontent worker. Found these when investigating user reports of image uploads not working for them. This PR wraps R2 `head`, `put`, and `get` calls in `retry()` (3 attempts, 500ms wait) with an error matcher for known transient patterns. The upload body is buffered to `ArrayBuffer` before retries since `ReadableStream` is single-use. Service binding calls (`validateUpload`, `confirmUpload`) get the same treatment. ### Change type - [x] `bugfix` ### Test plan - Cannot be manually tested (transient infra errors) ### Release notes - Fix transient R2 upload/download failures by adding retry logic ### Code changes | Section | LOC change | | ---------- | ---------- | | Core code | +30 / -7 | | Apps | +14 / -4 |
i couldn't, ahem, depend on what dependabot was doing in #8299 it was doing things like updating Next to the next major version for no apparent reason. this recreates it cleanly. (drive-by fix for a posthog link in perf tests) ### Change type - [ ] `bugfix` - [ ] `improvement` - [ ] `feature` - [ ] `api` - [x] `other`
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
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 : )