Today’s issue: Trent Reznor talks me out of learning React Native, Adam Wathan teaches us about component design, and Vitest helps me win back my kid’s college fund.
Welcome to #346.
My heart after you left me
But don’t worry, Framer
and Motion
are still friends, and they still love you very much – plus, you’ll get to have two Christmases from now on!
Ok, I’m actually talking about how the creator of Framer Motion, Matt Perry, recently announced that he’ll be leaving Framer-the-company and going independent with a spin-off project called Motion
.
Let’s take a closer look at why this is happening and where things go from here for the popular animation library.
How we got here: Back in 2018, Framer (a VC-backed web builder tool) acquired Matt’s simple-yet-powerful React animation library called PopMotion. Over the next six years, that project evolved into Framer Motion and became React’s go-to animation solution, with over 4.5 million weekly npm downloads.
But as the project has grown, so have Matt’s ambitions. He now wants the project to become “a core driver of animations on not just Framer sites, or just React sites, but all sites.”
That’s why he decided to spin out a new library called Motion as an independent, community-driven, open source project with a much wider mandate.
Here’s what you can expect from the new library:
Support for more frameworks: Motion will continue to support React, but it also comes with a Vanilla JS API that can integrate into your framework of choice. The hope is that the community can use the integration guides to build Motion for Angular, Svelte, Vue, etc.
Using the platform: Under the hood, Motion uses the latest browser APIs to get the best possible performance, while also supporting things the platform isn’t great at – like physics-based spring curves and interruptible animations.
Simple APIs: Writing complex, modern animations can turn into a huge mess if you aren’t an expert like Matt. Motion abstracts all that mess into a simple and powerful API.
Bottom Line: Even though Framer and Motion have officially broken up, it looks like they’ll stay friends. Framer became Motion’s first official sponsor, and I hear they’re doing a great job co-parenting their rare assortment of house plants and vintage Hello Kitty collectibles.
When you ship 100mb of images to your users
Unlike legacy CDNs, it generates image modifications in realtime, according to end-user requirements like browser, viewport, and connection speed. This saves major bandwidth and provides a better UX.
How tho? Every URL transformation generates a modified image version on the fly, while the original file stays intact. This transformed image gets cached on CDN nodes optimized for:
Scale – with smart resizing, cropping, and object zoom you can programmatically adapt images to any layout, without the need for extra editing tools (see docs)
Quality – image quality is automatically adjusted for maximum compression with no visible artifacts
Format – the CDN chooses the optimal format based on the user’s browser (AVIF, WebP, HEIC, Gif2Video or fallback to JPEG or PNG).
Plus, their adaptive image component lets you completely automate frontend hassles related to responsive design and easily generate responsive and optimized images based on specified breakpoints.
Try Uploadcare for free – it’s a no-brainer if your site has lots of images.
Their Appian WebViewer provides a powerful plugin with smart services that let users view, annotate, edit, redact, and sign documents without ever leaving Appian.
let seats = [
[1, 1, 0, 1, 0],
[0, 1, 1, 1, 0],
[1, 0, 1, 0, 0],
];
function reserveFirstAvailableSeat(seats) {
for (let i = 0; i < seats.length; i++) {
for (let j = 0; j < seats[i].length; j++) {
if (seats[i][j] === 0) {
seats[i][j] = 1; // Reserve the seat
console.log(`Reserved seat at row ${i + 1}, column ${j + 1}`);
break;
}
}
}
}
reserveFirstAvailableSeat(seats);
Nolan Sullivan wrote a comprehensive breakdown of Vitest vs. Jest to help me prepare for my upcoming Fantasy Testing Framework draft. Time to finally win back my kid’s college fund.
Vite 6.0 just came out, and we’ll write a full breakdown on it next week.
StackBlitz made this 6-minute YouTube video on how to use Supabase in your bolt.new app in order to store data and authenticate users. [sponsored]
injuly wrote an article called, Why am I writing a JavaScript toolchain in Zig? If I had to guess, I’d say it’s probably because you consumed too much expired cranberry sauce yesterday, but I’m no doctor.
The new React Aria release comes with new Accordion and Disclosure components, plus a few other goodies.
Kevin Grajeda wrote about a two-parameter approach to effortless spring UI animations
Adam Wathan gave a 45-minute talk at Laracon on Designing a Component Library, because apparently he has some experience with that.
Fernando Rojo wrote an article with a title that sounds like it could be the chorus of a Nine Inch Nails song: I learned React Native as a web developer, and I got everything wrong. “I focus on the pain, the only thing that’s real.”
jsontr.ee is a neat tool for visualizing JSON structures as dynamic tree diagrams.
Lord Tanner Linsley decreed that TanStack Start is ditching adapters.
The code ends up making 3 reservations instead of 1. This is because the break
statement only breaks out of the inner loop, not the outer loop. To fix this, you can replace the break
statement with a return
statement.
let seats = [
[1, 1, 0, 1, 0],
[0, 1, 1, 1, 0],
[1, 0, 1, 0, 0],
];
function reserveFirstAvailableSeat(seats) {
for (let i = 0; i < seats.length; i++) {
for (let j = 0; j < seats[i].length; j++) {
if (seats[i][j] === 0) {
seats[i][j] = 1; // Reserve the seat
console.log(`Reserved seat at row ${i + 1}, column ${j + 1}`);
return;
}
}
}
}
reserveFirstAvailableSeat(seats);
Alternatively, you can use labeled statements to explicitly break out of the outer loop:
let seats = [
[1, 1, 0, 1, 0],
[0, 1, 1, 1, 0],
[1, 0, 1, 0, 0],
];
function reserveFirstAvailableSeat(seats) {
rows: for (let i = 0; i < seats.length; i++) {
columns: for (let j = 0; j < seats[i].length; j++) {
if (seats[i][j] === 0) {
seats[i][j] = 1; // Reserve the seat
console.log(`Reserved seat at row ${i + 1}, column ${j + 1}`);
break rows;
}
}
}
}
reserveFirstAvailableSeat(seats);