Today’s issue: Remix teaming up with Roku, Rust invading servers, and Rich Harris inspiring my Halloween choices.
Welcome to #335.
me trying to score an influencer ticket to Next.js Conf
Believe me, I wanted to go to Next.js Conf.
I wanted to take pictures with all my favorite JavaScript influencers, cheer them on during their talks, and steal locks of their hair for my scrapbook tell them how much I appreciate their work.
But for some reason, I am no longer allowed to come within 100 yards of Lee Robinson in the state of California – so I had to follow the conference online instead.
Luckily, the biggest news actually dropped three days before Next Conf with the long-awaited release of Next.js 15. Let’s break down the highlights:
React 19 support – The App Router now uses React 19 (still in RC), and Next 15 also comes with experimental support for the React Compiler, which just hit beta. Chalk that up to the perks of employing half the React team.
Turbopack Dev is now stable – The next-gen bundler produces meaningfully faster code updates, local server startup, and initial route compilation for larger Next.js projects.
New caching semantics – GET
Route Handlers and the Client Router Cache are no longer cached by default, so fetch
fans can breathe a sigh of relief.
Async Request APIs – APIs like headers
, cookies
, and others that rely on request-specific data are now asynchronous. This means the server doesn’t have to wait for a request before rendering the content, and it helps set the stage for a more simplified rendering and caching model.
New @next/codemod
CLI – Codemods come with automated code transformations that make it easy and smooth to upgrade to the latest Next.js and React versions.
Bottom Line: Despite all the exciting new React frameworks coming out, Next’s market share is probably higher than it’s ever been. Will that continue in brave new React 19 world? Stay tuned.
When efficiency is your team’s #1 priority, but your QA cycles take hours
QA Wolf’s AI-native approach delivers 80% automated end-to-end test coverage for web and mobile apps in weeks, not years.
How it works:
They build and automate hundreds of tests for you in Playwright to test every single user flow, API, and third-party integration in your app.
Their infra lets you run 100% of your test suite in parallel, so your team can test and deploy continuously.
They sort all the real bugs from the flakes with human-verified bug reports – so you never waste time on flaky tests.
This case study breaks down how they saved AutoTrader $620k/yr in engineering time and increased the team’s release velocity by 20% – and there are dozens more cases like that.
Schedule a demo to learn more.
Their dicom conversion API lets you simply convert DICOM format files to PDFs without relying on any external dependencies.
function processUserData(userId, options = {}) {
"use strict";
let processedData = `User ID: ${userId}\n`;
if (options.includeEmail) {
processedData += "Email: user@example.com\n";
}
if (options.includeAge) {
processedData += "Age: 25\n";
}
if (options.verbose) {
processedData += "Processing mode: Verbose\n";
}
return processedData;
}
const userData = processUserData(12345, { includeEmail: true, verbose: true });
Jonathan Creamer wrote about how his team at Microsoft shrunk their JavaScript monorepo git size by 94%, and now I understand why big tech have to pay developers so much.
Convex Components are a new set of modular, TypeScript building blocks for your backend that help you confidently set up durable functions, real-time data management, third-party integrations, and more. [sponsored]
tinybench just released v3 of their simple, tiny, lightweight benchmarking library.
Tanner Linsley gave us all an early glimpse of TanStack Start with this conference talk at Netlify Compose. People were a lot more enthusiastic for this than my neighbors were about the “early glimpse” I gave them of my halloween costume – a moldy Lunchly.
Medusa just released v2.0 of its Node.js-powered ecomm platform. It’s a “complete rewrite of Medusa’s architecture and feature set”, so if you love ecommerce and breaking changes, you’re in luck.
Udoh wrote this 6-part deep dive on building a Remix app from scratch, which I hear was just green-lit to be made into a mini-series for the Roku channel.
Ian and Manoel wrote about why it took PostHog so long to build mobile session replay. Surprisingly, it’s not because they were spending all their time doodling cute hedgehogs – but because of some key technical challenges that make building replay for mobile a lot harder than building it for web. [sponsored]
pretzelhammer wrote about using Rust in non-Rust servers to improve performance. “The Rust will continue until morale performance improves.”
Eric Bailey wrote about making content-aware components using :has()
, grid, and quantity queries.
The Svelte team released a new CLI called sv
, which merges their previous CLIs and comes with built-in add-ons for formatting, linting, testing, auth and more. It’s so cool that it actually made me want to go as Rich Harris for Halloween, so I’ll need to find an accent coach, a hair stylist, and someone to sell my previous costume to asap.
From MDN - “The ‘use strict’ directive can only be applied to the body of functions with simple parameters. Using “use strict” in functions with rest, default, or destructured parameters is a syntax error.”
There are a few ways to fix this. We can move the "use strict"
directive to the top of the file, or we can remove the default parameter from the function signature, but if we wanted to keep both the default parameter and the "use strict"
directive, we can go old school and check if the options parameter is undefined and set it to an empty object.
function processUserData(userId, options) {
"use strict";
if (typeof options !== "object" || options === null) {
options = {};
}
let processedData = `User ID: ${userId}\n`;
if (options.includeEmail) {
processedData += "Email: user@example.com\n";
}
if (options.includeAge) {
processedData += "Age: 25\n";
}
if (options.verbose) {
processedData += "Processing mode: Verbose\n";
}
return processedData;
}
const userData = processUserData(12345, { includeEmail: true, verbose: true });