😬 React Router deprecated its viewTransition prop. The replacement needs transitions left on.
The old props still run for all of v8, including on older React. They leave in v9.
React Router 8.5, out yesterday, deprecates viewTransition, useViewTransitionState, and NavLink's isTransitioning. The replacement is React 19.3's ViewTransition wrapped around Outlet in a layout that stays mounted. That component only animates when React transitions are enabled, so a router created with useTransitions={false} will not get the new animation.
The same release adds an unstable mode, ssr: "unstable_api-only": static HTML on a CDN, loaders and actions on a server that can sit on another origin. The changelog says not to use unstable features in production.
🤨 The swipe never hits JavaScript. The sheet is the bottom half of a box twice the screen tall.
The drag is a scroll. Closed is scroll position zero, so the window clips the sheet off screen. Opening scrolls that box to the bottom.
React Aria's Sheet hides the scrollbar with scrollbar-width: none and snaps at the top and bottom of the sheet, so it stops fully open or fully closed. Momentum and the rubber-band are the browser's. A touch listener is not on that path.
A peek is the awkward part. While the sheet is only partly open, the content inside is overflow: hidden, so a list in there will not move until the sheet is fully open. Those partial heights are invisible 1px markers with scroll-margin-top: 100dvh. The fade that tracks the finger is a view-timeline, inset by 100dvh. Firefox still does not ship view-timeline, so that fade is the piece to feature-detect. The scroll itself is ordinary overflow.
JavaScript still unmounts the sheet. An IntersectionObserver fires once it has left the viewport. And dvh does not shrink when the iOS keyboard opens, so the content gets padding-bottom: calc(100dvh - var(--visual-viewport-height)).
🤨 A cached function that returns two typed arrays can run code on the server.
No login required. Next.js says to upgrade even if you never wrote a function like that.
Yesterday's patch, 16.4.1 and 15.5.28, closes three bugs, two of them held back from the September release. On 16.0.0 through 16.4.0, App Router plus Cache Components, a 'use cache' function that returns more than one typed array is unauthenticated remote code execution. There is no workaround. Same class of bug in React: GHSA-xqc2-xf4c-x3h3.
The one that reaches older apps is image optimization. On glibc Linux, an SVG through the optimizer can also run code, from Next 10 through 15.5.27 and on the 16.x line through 16.4.0. CVE-2026-96889. sharp 0.35.5 or newer is the stopgap. The patched Next versions pull it in.
A third bug, rated High: one Server Action on the App Router is enough for a request to pin that process's CPU. Pages Router, and apps with no Server Actions, are not affected.
The usual advice is still right. Put width and height on the image and the browser reserves the box before the file arrives. Chrome turns width="1200" height="630" into aspect-ratio: auto 1200 / 630.
Then a guide about fixing layout shift added one more line: aspect-ratio: attr(width) / attr(height). Untyped attr() comes back as a raw string, and a string is not a ratio. In Chrome 154 that declaration computed to auto and replaced the ratio the browser had already figured out. The image was 0px tall until it loaded, then 168. Without that line it was 168 the whole time.
The typed form kept the space. Deleting the line is the better fix. The attributes were already doing the job.
🤨 The design file did not teach Claude your components
Claude already found them. Across 49 builds, in the site's own repo and in a fresh app, it imported Button, Select, Input, and the toast. Not one of those builds invented a hex color.
What the file changed was taste. Without it, four of five pages grew six yellow buttons: hero, four cards, and the form. The file says one per screen. All seven builds that had it loaded stopped at one.
The actual break was dumber. When a link was the only way to reach the package, and there was no list of components, three of five builds imported from a path that does not exist.
Small test. One page, one author. The split is still worth keeping. Finding the components was already solved. The rule about how the screen should look was not.
👀 He published a TypeScript compiler he has never read
Over $400k in tokens, more than a million lines of Rust, and the port still died at about 84%. Then another model threw all of that away and shipped a checker that, according to the README, passes 181,711 tests and beats Microsoft's own Go compiler. On VS Code that is 4.2 seconds instead of 6.8.
The uncomfortable part is his, not the benchmark. He has not read a line of this code, and he is not sure the install even works.
This is not your new tsc. It is pinned to a September 29 TypeScript 7.1 dev build, monorepos still misbehave, and Bun's checker is faster besides. The $400k port was not a foundation. Starting over was. A green test suite is the only review this compiler has.
The list was fine. The user asked for fresh data. The type moved to loading, and loading has no rows, so the people disappeared until the response came back. Calling that variant refreshing does not make it kinder.
The rows and the request are two different machines. Let callState flip to loading beside the data, and to error if the refresh fails. CallState can still forbid "loading and an error at once". It should not make the list leave the room.