<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Victoria</title>
    <description>The latest articles on DEV Community by Victoria (@hugaidas).</description>
    <link>https://dev.to/hugaidas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F890340%2F29e6f9fe-6727-4fd3-8ac0-6dd0856e9be5.jpeg</url>
      <title>DEV Community: Victoria</title>
      <link>https://dev.to/hugaidas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hugaidas"/>
    <language>en</language>
    <item>
      <title>Beyond Next.js: TanStack Start and the Future of Full-Stack React Development</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Sun, 14 Dec 2025 22:08:17 +0000</pubDate>
      <link>https://dev.to/hugaidas/beyond-nextjs-tanstack-start-and-the-future-of-full-stack-react-development-2m5h</link>
      <guid>https://dev.to/hugaidas/beyond-nextjs-tanstack-start-and-the-future-of-full-stack-react-development-2m5h</guid>
      <description>&lt;p&gt;For the last five years, Next.js was the "safe" default. Whether you were building a personal blog or a complex SaaS, the advice was always: &lt;em&gt;Just use Next.&lt;/em&gt; But lately, that conversation has changed. As Next.js evolved from a simple tool into a massive, "magic-heavy" ecosystem, the developer experience changed with it. Between complex caching rules and rigid server-client boundaries, we’ve reached a point where we often feel less like architects and more like we’re just troubleshooting the framework's assumptions. &lt;/p&gt;

&lt;p&gt;We aren’t looking for another framework just for the sake of it; we’re looking for a return to clarity. We want to enjoy the build again without fighting the tool we chose to help us. That’s where &lt;strong&gt;TanStack Start&lt;/strong&gt; enters the arena — it feels like the "reset button" the ecosystem needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Complexity Tax" of the Modern Web
&lt;/h2&gt;

&lt;p&gt;Starting with Next.js 13, things became less stable. React Server Components (RSC) were introduced alongside the App Router, and the framework began changing its foundational assumptions frequently.&lt;/p&gt;

&lt;p&gt;Suddenly, everything became "server-side by default." We entered a world of &lt;code&gt;'use client'&lt;/code&gt;, &lt;code&gt;'use server'&lt;/code&gt;, and the &lt;code&gt;'use cache'&lt;/code&gt; directive. The paradigm flipped entirely, bringing frequent hydration problems.&lt;/p&gt;

&lt;p&gt;We adapted to the idea that everything was cached by default in Next.js 14. Then &lt;a href="https://nextjs.org/blog/next-15" rel="noopener noreferrer"&gt;Next.js 15 arrived with Turbopack&lt;/a&gt; and a completely inverted mental model: nothing is cached by default. You now have to explicitly opt-in to &lt;a href="https://nextjs.org/docs/app/api-reference/directives/use-cache" rel="noopener noreferrer"&gt;caching behavior&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Next.js 15 - Explicit caching with 'use cache' directive&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next.js 15 made Turbopack the default (or at least heavily promoted) build tool, moving away from Webpack. The Rust-based bundler promised 10x performance improvements, but &lt;a href="https://github.com/vercel/next.js/discussions/77102" rel="noopener noreferrer"&gt;developers report variable experiences&lt;/a&gt; — excelling at hot refresh but struggling with broken imports, high resources consumption, and cold starts.&lt;/p&gt;

&lt;p&gt;The fact that Vercel published an official guide titled &lt;a href="https://vercel.com/blog/common-mistakes-with-the-next-js-app-router-and-how-to-fix-them" rel="noopener noreferrer"&gt;"Ten Common Mistakes with the Next.js App Router"&lt;/a&gt; speaks for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  TanStack Start Enters the Arena
&lt;/h2&gt;

&lt;p&gt;TanStack has serious credibility. They've been shipping battle-tested tools that developers actually use for years:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwt1jioe6yfo3llmprcp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxwt1jioe6yfo3llmprcp.png" alt="TanStack family" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Out of curiosity, I &lt;a href="https://github.com/HugaidaS/yerevan-culinary-travel-app" rel="noopener noreferrer"&gt;built an app&lt;/a&gt; while it was still a beta, and now it is v1 already, and everything works without friction.&lt;/p&gt;

&lt;p&gt;Solid foundation is simple, TanStack Start is built on two key technologies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TanStack Router&lt;/strong&gt; (the entire routing layer with type safety)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vite&lt;/strong&gt; (an industry-standard build tool)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Core Philosophical Difference: Client-First vs Server-First
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Next.js 15: Server-First Architecture
&lt;/h3&gt;

&lt;p&gt;Every component is a React Server Component by default. You start on the server and explicitly opt into client-side interactivity with &lt;code&gt;'use client'&lt;/code&gt;. This excels for content-heavy websites and SEO-critical catalogs.&lt;/p&gt;

&lt;h3&gt;
  
  
  TanStack Start: Client-First with Selective SSR
&lt;/h3&gt;

&lt;p&gt;TanStack Start assumes you are building an interactive app. You have fine-grained control over the rendering mode via the &lt;code&gt;ssr&lt;/code&gt; property on each route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pure client-side rendering (like a traditional SPA)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFileRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/dashboard&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
  &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DashboardComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Full SSR for SEO-critical pages&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFileRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
  &lt;span class="na"&gt;ssr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fetchProducts&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductsComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz1zoptyr468hhaaz3qi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz1zoptyr468hhaaz3qi.png" alt="TanStack features" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature-by-Feature Comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Routing with Type Safety
&lt;/h3&gt;

&lt;p&gt;The framework generates a &lt;code&gt;routeTree.gen.ts&lt;/code&gt; &lt;a href="https://github.com/HugaidaS/yerevan-culinary-travel-app/blob/master/src/routeTree.gen.ts" rel="noopener noreferrer"&gt;file&lt;/a&gt;. If you change a route parameter, every link using that route fails at build time — not at runtime.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next.js 15 Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/products/[slug]/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// In a component - just strings, no type checking&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Link&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TanStack Start Example
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// routes/products.$id.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFileRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products/$id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// params.id is fully typed automatically&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Navigation with compile-time safety&lt;/span&gt;
&lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products/$id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://tanstack.com/router/v1/docs/framework/react/guide/type-safety" rel="noopener noreferrer"&gt;Learn more in the TanStack Router Type Safety guide.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Data Fetching: Isomorphic Loaders vs Async Server Components
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Next.js 15 Approach
&lt;/h4&gt;

&lt;p&gt;Next.js uses Async Server Components that run exclusively on the server. If you need this data on the client for subsequent interactions, the framework has to re-fetch or stream from the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/page.tsx - Async Server Component&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[https://api.example.com/data](https://api.example.com/data)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TanStack Start Approach
&lt;/h4&gt;

&lt;p&gt;TanStack uses &lt;strong&gt;isomorphic loaders&lt;/strong&gt; — the same code runs on the server during the initial load (for SEO/speed) and on the client during subsequent navigations. This avoids the "waterfall" and server round-trips for every UI transition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFileRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products/$id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/execution-model" rel="noopener noreferrer"&gt;Learn about the execution model.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Server Functions: Flexibility vs Convention
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Next.js 15 Server Actions
&lt;/h4&gt;

&lt;p&gt;Primarily designed for forms and mutations, Server Actions are POST-only and can feel tightly coupled to the render cycle.&lt;/p&gt;

&lt;h4&gt;
  
  
  TanStack Start Server Functions
&lt;/h4&gt;

&lt;p&gt;Support any HTTP method, built-in validation with Zod, and composable middleware for things like auth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createServerFn&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/server-functions" rel="noopener noreferrer"&gt;Learn more in the TanStack Start Server Functions guide.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. SEO: Static Metadata vs Dynamic Head Management
&lt;/h3&gt;

&lt;p&gt;Next.js uses &lt;code&gt;generateMetadata&lt;/code&gt;. TanStack Start uses a &lt;code&gt;head&lt;/code&gt; function that receives fully-typed &lt;code&gt;loaderData&lt;/code&gt;. Child routes can override parent route meta tags intelligently without re-fetching data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next.js 15 Metadata
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Often fetched again if not cached&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  TanStack Start Head
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createFileRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products/$id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt;
  &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;loaderData&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loaderData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;loaderData&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Build Tooling: Vite vs Turbopack
&lt;/h3&gt;

&lt;p&gt;Next.js 15 is pushing Turbopack, which is still maturing. TanStack Start uses &lt;strong&gt;Vite&lt;/strong&gt;, which has been battle-tested for years with a massive plugin ecosystem and predictable performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Deployment: Vendor Lock-in vs True Flexibility
&lt;/h3&gt;

&lt;p&gt;Next.js is heavily optimized for Vercel. TanStack Start doesn't care where you deploy. Deploy to &lt;a href="https://developers.cloudflare.com/workers/framework-guides/web-apps/tanstack-start/" rel="noopener noreferrer"&gt;Cloudflare Workers&lt;/a&gt;, &lt;a href="https://docs.netlify.com/build/frameworks/framework-setup-guides/tanstack-start/" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;, or any Node.js server. &lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=gBEZ9SYfFDU" rel="noopener noreferrer"&gt;Deploy TanStack Start in less than a minute.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fageq49cm72xnpxe4vfsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fageq49cm72xnpxe4vfsz.png" alt="Deployment options" width="800" height="699"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Developer Experience: Next.js 15 vs TanStack Start
&lt;/h3&gt;

&lt;p&gt;The configuration and debugging experience is a fundamental difference. TanStack provides deep state-inspection tools, rich configuration options to choose from, and many other things that Next.js lacks to sweeten our developer's life.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TanStack Start UI/Console:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pq1z3ethwcifq4zc8i7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pq1z3ethwcifq4zc8i7.gif" alt="UI Console config" width="600" height="356"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbxenhfvy67q520ileh4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbxenhfvy67q520ileh4.gif" alt="DevTools demo" width="600" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next.js 15 Console:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F417tqlzvjk2gnivnsqsy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F417tqlzvjk2gnivnsqsy.gif" alt="Next.js configuration" width="800" height="475"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jb8qv5xkmtd88kgwaoc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0jb8qv5xkmtd88kgwaoc.gif" alt="Next.js 15 dev tools" width="760" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Choose Each Framework
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choose Next.js 15 if:&lt;/strong&gt; Building content-heavy sites (blogs, e-commerce) where SEO is mission-critical and you are deploying to Vercel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose TanStack Start if:&lt;/strong&gt; Building highly interactive applications (dashboards, SaaS), you need deployment flexibility, and type safety is non-negotiable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://tanstack.com/router/v1/docs/framework/react/comparison" rel="noopener noreferrer"&gt;View the full comparison table here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The React ecosystem has been a bit of a monopoly lately, and let's be honest — nobody actually likes a monopoly unless they're playing a board game. &lt;/p&gt;

&lt;p&gt;The arrival of TanStack Start is just healthy competition. It’s not about "killing" Next.js; it's about having a choice again. We finally have an alternative that prioritizes explicitness over magic and stability over constant reinvention. Healthy competition keeps the ecosystem sharp and gives us the freedom to pick the tool that actually fits the job. It’s time to stop fighting the defaults and start enjoying the build again.&lt;/p&gt;




&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Next.js 15
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/blog/next-15" rel="noopener noreferrer"&gt;Next.js 15 Release Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app" rel="noopener noreferrer"&gt;Next.js App Router Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/directives/use-cache" rel="noopener noreferrer"&gt;Next.js &lt;code&gt;use cache&lt;/code&gt; Directive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vercel.com/blog/common-mistakes-with-the-next-js-app-router-and-how-to-fix-them" rel="noopener noreferrer"&gt;Common Mistakes with App Router&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  TanStack Start
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/start/latest" rel="noopener noreferrer"&gt;Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/blog/announcing-tanstack-start-v1" rel="noopener noreferrer"&gt;TanStack Start v1 Release Announcement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/router/v1/docs/framework/react/guide/type-safety" rel="noopener noreferrer"&gt;TanStack Router Type Safety Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/selective-ssr" rel="noopener noreferrer"&gt;Selective SSR Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/start/latest/docs/framework/react/guide/server-functions" rel="noopener noreferrer"&gt;Server Functions Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=gBEZ9SYfFDU" rel="noopener noreferrer"&gt;Deploy in One Minute (Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://frontendmasters.com/blog/introducing-tanstack-start/" rel="noopener noreferrer"&gt;Frontend Masters: Introduction to TanStack Start&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/router/v1/docs/framework/react/comparison" rel="noopener noreferrer"&gt;TanStack Router vs Next.js Comparison&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>nextjs</category>
      <category>react</category>
    </item>
    <item>
      <title>New and Most Interesting in Web UI from Google I/O 2025 (with demos)</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Tue, 03 Jun 2025 17:35:25 +0000</pubDate>
      <link>https://dev.to/hugaidas/new-and-most-interesting-in-web-ui-from-google-io-2025-with-demos-73g</link>
      <guid>https://dev.to/hugaidas/new-and-most-interesting-in-web-ui-from-google-io-2025-with-demos-73g</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Every web developer has struggled with dropdown menus, carousels, and UI components that seem deceptively simple. But what if these patterns could be built natively with ease? At Google I/O 2025, Una Kravets showed us exactly how the latest updates in HTML and CSS are redefining what’s possible. Web UI has undergone a significant transformation, with new technologies making interfaces more powerful and accessible. This article explores three key innovations: the evolution of the dialog vs. popover that enables us to build a customizable select menu from scratch, the introduction of a native scroll component, and a new hover card feature that is closely related to the new world of popovers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7k66lo07n6i4iy70r0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7k66lo07n6i4iy70r0w.png" alt=" " width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. New Dialog vs. Popover
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8moa8yknup4t1rrovjuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8moa8yknup4t1rrovjuh.png" alt="Dialog vs Popover" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s start with something surprisingly powerful: dialogs and popovers without a single line of JavaScript. Thanks to the new &lt;code&gt;command&lt;/code&gt; attribute pattern, you can control dialog and popover visibility declaratively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;command=&lt;/span&gt;&lt;span class="s"&gt;"show-modal"&lt;/span&gt; &lt;span class="na"&gt;commandfor=&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Show Side Dialog&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;dialog&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"slide-out"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Close"&lt;/span&gt; &lt;span class="na"&gt;command=&lt;/span&gt;&lt;span class="s"&gt;"close"&lt;/span&gt; &lt;span class="na"&gt;commandfor=&lt;/span&gt;&lt;span class="s"&gt;"demo"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"material-symbols-outlined"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;close&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt; 
&lt;span class="nt"&gt;&amp;lt;/dialog&amp;gt;&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, both &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;popover&amp;gt;&lt;/code&gt; elements have evolved to offer different interaction models. Popovers support light dismiss (i.e., clicking outside closes them), anchor positioning, and declarative usage, while dialogs now support &lt;code&gt;closedby="any"&lt;/code&gt; to allow more flexible closing behavior, making them act a bit more like popovers while keeping their modal essence.&lt;/p&gt;

&lt;p&gt;You can control the 'light-dismiss' option and specify which element triggers the dialog to close by using this &lt;code&gt;[closeby]&lt;/code&gt; attribute, and no JavaScript required:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fch3ic4uxgvu2rs3sfx0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fch3ic4uxgvu2rs3sfx0s.png" alt=" " width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check out a working example here: &lt;a href="https://codepen.io/ellinsa/pen/YPXqLrP" rel="noopener noreferrer"&gt;Zero JavaScript Dialog Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ll revisit popovers again when we get to hover cards, since there's even more to cover.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Native Select Component
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1pet23clprlkr5ztcya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1pet23clprlkr5ztcya.png" alt="Customizable select status" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Customizing a &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; element has always been a pain — either you accepted the default browser styling or ended up rebuilding it from scratch with divs and JS. But that’s changing. With the new popover-based &lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; and anchor positioning, you can now fully style and control the component while preserving accessibility and form behavior.&lt;/p&gt;

&lt;p&gt;New pseudo-elements, HTML elements, and built-in styling for options and checkmarks let you build something custom without hacks.&lt;/p&gt;

&lt;p&gt;Here’s a breakdown of the new anatomy:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faisb9ctiywk4l2rhafph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faisb9ctiywk4l2rhafph.png" alt="Customizable select anatomy" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Play with the full demo here: &lt;a href="https://codepen.io/ellinsa/pen/xbGVJGr" rel="noopener noreferrer"&gt;Customizable Select Demo&lt;/a&gt;&lt;br&gt;&lt;br&gt;
You’ll also get a feel for how anchoring works—a feature introduced at the same time.&lt;/p&gt;

&lt;p&gt;To better visualize this anchoring logic, check out this &lt;a href="https://chrome.dev/anchor-tool/" rel="noopener noreferrer"&gt;Anchor tool&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  A word of caution
&lt;/h3&gt;

&lt;p&gt;As noted in &lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select" rel="noopener noreferrer"&gt;this MDN article&lt;/a&gt;, the new &lt;code&gt;&amp;lt;selectedcontent&amp;gt;&lt;/code&gt; may cause issues if you're dynamically updating &lt;code&gt;&amp;lt;option&amp;gt;&lt;/code&gt; elements using JavaScript — those changes won’t automatically reflect inside &lt;code&gt;&amp;lt;selectedcontent&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And yes, support is still limited right now, so use it wisely in production apps.&lt;/p&gt;

&lt;p&gt;To see a real-time walkthrough from the conference, here’s the &lt;a href="https://youtu.be/XASRYAR7S5w?t=2722" rel="noopener noreferrer"&gt;timestamped demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Building a New Native Scroll Component
&lt;/h2&gt;

&lt;p&gt;Creating smooth, accessible sliders or carousels has always meant reaching for external libraries or building your own logic. But now, CSS is making native scroll components a reality. You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;scroll-button&lt;/code&gt; pseudo-elements (for navigation controls)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scroll-marker&lt;/code&gt; (for quick jump-to-points)&lt;/li&gt;
&lt;li&gt;Scroll-driven animations (yes, native!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the anatomy of this new "slider":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrj9x4walvfs40pqrzk4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrj9x4walvfs40pqrzk4.png" alt="Carousel anatomy" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This opens up a lot — tabs, carousels, progress steppers, multi-step forms, you name it. And small details like scroll shadows (that used to require JS or weird hacks) are now a breeze:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyt632t2nge9dm6t74gj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyt632t2nge9dm6t74gj.png" alt="Shadow scrollable" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There’s a lot more to explore when it comes to &lt;code&gt;scroll-state&lt;/code&gt;, so I recommend diving into &lt;a href="https://chrome.dev/carousel/" rel="noopener noreferrer"&gt;Google’s official carousel demos&lt;/a&gt;. All the examples are editable, and the source code is available — great for learning or adapting for your own use.&lt;/p&gt;

&lt;p&gt;Want something more interactive? Play with the &lt;a href="https://chrome.dev/carousel-configurator/" rel="noopener noreferrer"&gt;Carousel Configurator&lt;/a&gt;. You can toggle options and see how the styles and behaviors change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlwi2687ei6o29sgr002.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlwi2687ei6o29sgr002.png" alt="Carousel configurator demo" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond saving time, this new CSS-driven approach reduces JS payload and improves maintainability.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If there's no code — there's nothing to maintain.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1phvz6oqat0t7n73oswe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1phvz6oqat0t7n73oswe.png" alt="CSS only carousel benefit" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Hover Card
&lt;/h2&gt;

&lt;p&gt;Hover cards take the popover magic even further. Alongside &lt;code&gt;popover&lt;/code&gt;, we now have attributes like &lt;code&gt;interesttarget&lt;/code&gt; and &lt;code&gt;popovertarget&lt;/code&gt;, unlocking more nuanced interactions.&lt;/p&gt;

&lt;p&gt;Basically, there are now three types of popovers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiwhn56opsgebdokf1kc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxiwhn56opsgebdokf1kc.png" alt="3 types of popovers" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s say you want to show extra context when the user hovers over something — no click required. Combine &lt;code&gt;interesttarget&lt;/code&gt; with a popover and voilà:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbj85m7ofr1p5nwzp90lk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbj85m7ofr1p5nwzp90lk.png" alt="popover + interest target" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s a simplified hover card using just a popover:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F443x8swvqadyhl7ger17.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F443x8swvqadyhl7ger17.png" alt="interest target demo" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can fully customize it too:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdv2t1lni2srqw075x0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdv2t1lni2srqw075x0q.png" alt="hover card customization" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Important to note: this animation behavior differs from a typical &lt;code&gt;:hover&lt;/code&gt; effect — it’s more dynamic, controllable, and has delay/interest thresholds built-in.&lt;/p&gt;

&lt;p&gt;Watch the live example &lt;a href="https://youtu.be/XASRYAR7S5w?t=4162" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feeling confused by all these new attributes? Don’t worry — it takes a bit of hands-on play to internalize it. You can dig deeper via the &lt;a href="https://open-ui.org/components/interest-invokers.explainer/" rel="noopener noreferrer"&gt;Interest Invokers explainer&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover" rel="noopener noreferrer"&gt;Popover documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The short version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;interesttarget&lt;/code&gt; = hover for a moment, show something&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;popovertarget&lt;/code&gt; = click or focus, show something&lt;/li&gt;
&lt;li&gt;You can mix and match for rich interactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The future of Web UI is more declarative, accessible, and efficient. As these features roll out more widely, we can ditch a lot of the boilerplate and focus on creativity instead.&lt;/p&gt;

&lt;p&gt;Yes, it can feel overwhelming, especially for newer devs. But you don’t need to memorize every detail. Just knowing these features exist is half the battle. When a problem arises later, you’ll remember, “Oh yeah, I saw a demo about that,” and you’ll know where to look.&lt;/p&gt;

&lt;p&gt;It’s not about memorizing — it’s about exposure.&lt;/p&gt;

&lt;p&gt;With these updates, we’re entering a golden era of UI development. Less JavaScript. More clarity. Better accessibility. And honestly? A lot more fun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://youtu.be/XASRYAR7S5w?t=1772" rel="noopener noreferrer"&gt;Google I/O Web Day 3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.dev/" rel="noopener noreferrer"&gt;Google Demos&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Customizable_select" rel="noopener noreferrer"&gt;Customizable select demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://open-ui.org/components/interest-invokers.explainer/" rel="noopener noreferrer"&gt;Interest invokers proposal&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/popover" rel="noopener noreferrer"&gt;Popover MDN docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://webstatus.dev/" rel="noopener noreferrer"&gt;Web Status Platform dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/blog/web-at-io25" rel="noopener noreferrer"&gt;10 updates from Google I/O 2025&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding Checksums in Ethereum: Why They Matter for Web3 Developers</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Sun, 09 Feb 2025 15:40:04 +0000</pubDate>
      <link>https://dev.to/hugaidas/understanding-checksums-in-ethereum-why-they-matter-for-web3-developers-2oee</link>
      <guid>https://dev.to/hugaidas/understanding-checksums-in-ethereum-why-they-matter-for-web3-developers-2oee</guid>
      <description>&lt;p&gt;Many Web3 and blockchain developers have encountered an issue where their specified address fails due to a checksum error. But what exactly is a checksum, and why is it so important?&lt;/p&gt;

&lt;p&gt;In this article, we'll break it down in simple terms, explore how checksums are used in Ethereum, and provide practical tips for Web3 developers on working with them. Let’s dive in!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t30r1o3i3ktbdnsbn73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3t30r1o3i3ktbdnsbn73.png" alt=" " width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Checksum?
&lt;/h2&gt;

&lt;p&gt;A checksum is a small piece of data derived from other data to detect errors during transmission or user input. In blockchains, checksums are often calculated for addresses and appended in some way to ensure integrity. This prevents sending funds to invalid addresses due to typos or data corruption.&lt;/p&gt;

&lt;p&gt;For example, when sending funds to an Ethereum address, wallets and blockchain clients use checksums to verify whether the address is correctly formatted before proceeding with the transaction. This simple mechanism helps prevent costly mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checksum in Ethereum
&lt;/h2&gt;

&lt;p&gt;Ethereum introduced the checksum standard in &lt;a href="https://eips.ethereum.org/EIPS/eip-55" rel="noopener noreferrer"&gt;EIP-55&lt;/a&gt; back in 2016. The idea is simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert the address to lowercase hex.&lt;/li&gt;
&lt;li&gt;Hash the lowercase address using Keccak-256.&lt;/li&gt;
&lt;li&gt;If a character in the original address is a letter (a-f), make it uppercase if the corresponding hash bit is 1; otherwise, keep it lowercase.&lt;/li&gt;
&lt;li&gt;This approach has several benefits:&lt;/li&gt;
&lt;li&gt;It remains backward-compatible with hex parsers that accept mixed case.&lt;/li&gt;
&lt;li&gt;It keeps the length at 40 characters.&lt;/li&gt;
&lt;li&gt;It significantly reduces the probability of mistyped addresses being accepted as valid (~0.0247%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example implementation in JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createKeccakHash = require('keccak');

function toChecksumAddress(address) {
  address = address.toLowerCase().replace('0x', '');
  var hash = createKeccakHash('keccak256').update(address).digest('hex');
  var ret = '0x';

  for (var i = 0; i &amp;lt; address.length; i++) {
    ret += parseInt(hash[i], 16) &amp;gt;= 8 ? address[i].toUpperCase() : address[i];
  }

  return ret;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you prefer a simpler implementation, you can use &lt;a href="https://viem.sh/docs/utilities/getAddress.html" rel="noopener noreferrer"&gt;Viem&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { getAddress } from 'viem';

console.log(getAddress('0xa5cc3c03994db5b0d9a5eEdD10Cabab0813678ac'));
// Output: '0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Viem simplifies the process, ensuring you always get a checksummed address with minimal effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  The EIP-1191 Extension: Adding Chain IDs to Checksums
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ethereum/EIPs/issues/1121" rel="noopener noreferrer"&gt;EIP-1191&lt;/a&gt; extends EIP-55 by incorporating chain IDs into the checksum calculation. The goal is to prevent users from mistakenly sending funds to an address on a different network, such as Ethereum Mainnet vs. Ethereum Testnet.&lt;/p&gt;

&lt;p&gt;How It Works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The address is converted using the same EIP-55 rules.&lt;/li&gt;
&lt;li&gt;If a registered chain ID is provided, it is added to the hash input.&lt;/li&gt;
&lt;li&gt;The resulting checksum-encoded address helps differentiate addresses across networks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, there is a tradeoff:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EIP-1191 addresses are not backward-compatible with standard EIP-55 checksummed addresses.&lt;/li&gt;
&lt;li&gt;Some tools and applications relying on EIP-55 might not recognize them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many major tools, including Trezor, Ledger, MEW, MyCrypto, and Web3.js, have adopted EIP-1191. However, MetaMask defaults to EIP-55 and will flag invalid checksums when manually modifying an address.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
If you paste an Ethereum address without a checksum into &lt;a href="https://etherscan.io/" rel="noopener noreferrer"&gt;Etherscan&lt;/a&gt;, it will automatically show you the checksummed version, helping you avoid errors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Web3 Developers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always use checksummed addresses to prevent user errors and ensure compatibility with major tools.&lt;/li&gt;
&lt;li&gt;Use libraries like Viem to handle checksums effortlessly.&lt;/li&gt;
&lt;li&gt;Be aware of EIP-1191 limitations and ensure your app supports the appropriate checksum format based on network requirements.&lt;/li&gt;
&lt;li&gt;Validate addresses before sending transactions to prevent costly mistakes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these practices, you can make your dApp safer and improve the user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Checksums play a crucial role in blockchain security, preventing address-related mistakes that could lead to lost funds. Understanding EIP-55 and EIP-1191 helps developers write more robust and secure Web3 applications. Whether you're manually validating addresses or using a library like Viem, always ensure you're working with the correct checksummed format.&lt;/p&gt;

&lt;p&gt;Even though a deep understanding of checksums is not strictly required, having at least a brief knowledge of this concept will enhance your general expertise in the field. It can help you avoid unnecessary debugging, prevent certain bugs, and demonstrate a higher level of proficiency as a Web3 developer.&lt;/p&gt;

&lt;p&gt;For further reading, check out these resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/coinmonks/ethereum-checksummed-addresses-importance-and-implementation-eef74aa3ae18" rel="noopener noreferrer"&gt;Ethereum Checksum Addresses – CoinMonks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://viem.sh/docs/utilities/getAddress.html" rel="noopener noreferrer"&gt;Viem Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ethereum/EIPs/issues/1121" rel="noopener noreferrer"&gt;Ethereum EIP-1191 Proposal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Rendering Strategies in Next.js</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Wed, 30 Oct 2024 12:48:14 +0000</pubDate>
      <link>https://dev.to/hugaidas/rendering-strategies-in-nextjs-4jnk</link>
      <guid>https://dev.to/hugaidas/rendering-strategies-in-nextjs-4jnk</guid>
      <description>&lt;p&gt;Hello, long time no see! How’s everyone doing?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d8cp849vqjhvrzymjuk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d8cp849vqjhvrzymjuk.png" alt=" " width="498" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently, I’ve been diving deep into Next.js 15, brushing up on some fundamental concepts and exploring a new favorite topic: rendering strategies. This one’s for anyone curious about the ins and outs of SSR (Server-Side Rendering) and all its sibling strategies in Next.js. Whether you’re just starting or need a refresher, consider this your go-to memo on rendering strategies!&lt;/p&gt;

&lt;h2&gt;
  
  
  SSR (Server-Side Rendering) in Next.js vs. CSR (Client-Side Rendering)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How SSR Works
&lt;/h3&gt;

&lt;p&gt;In SSR, Next.js pre-renders the page on the server at each request. If you’ve ever added a fetch request at the top of a functional component in Next, then hit refresh to update the data, you’re already using SSR.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sww02q5wc76r06x8plg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sww02q5wc76r06x8plg.png" alt=" " width="800" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One game-changer with the latest updates is the &lt;a href="https://nextjs.org/docs/app/api-reference/next-config-js/serverComponentsHmrCache" rel="noopener noreferrer"&gt;serverComponentsHmrCache&lt;/a&gt; feature. This allows us to cache fetch responses in server components across HMR (hot module replacement) refreshes in development mode. So, every refresh becomes a faster, cheaper, and more efficient experience, especially when billed API calls are involved.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of SSR:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Improved Initial Load Time: Faster than CSR, especially for first-time visitors.&lt;/li&gt;
&lt;li&gt;SEO-Friendly: Search engines love SSR since content is ready when they crawl.&lt;/li&gt;
&lt;li&gt;Reduced FCP (First Contentful Paint): Faster perceived loading experience for users.&lt;/li&gt;
&lt;li&gt;Direct Database Calls: With SSR, data fetching logic can stay server-side, making direct database calls possible without needing to build API endpoints.&lt;/li&gt;
&lt;li&gt;Automatic Request Deduplication: A lesser-known perk—when the same data is requested multiple times, only one request is sent.&lt;/li&gt;
&lt;li&gt;Enhanced Security: Keeps sensitive data server-side, never exposing API keys on the client.&lt;/li&gt;
&lt;li&gt;Reduced Network Waterfall: SSR fetches data in parallel, avoiding sequential delays.&lt;/li&gt;
&lt;li&gt;JS Optional: Users can still access content if their browser has JavaScript disabled.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  CSR (Client-Side Rendering)
&lt;/h2&gt;

&lt;p&gt;In CSR, you start by declaring an empty state and conduct a fetch request within useEffect. Once the data arrives, you update the state and UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trade-Offs:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Empty Page at First: Users see an empty shell until data is loaded, which can impact user experience and SEO.&lt;/li&gt;
&lt;li&gt;Full Control Over State: Great for interactive pages where user actions trigger updates.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rendering Strategies Overview
&lt;/h2&gt;

&lt;p&gt;Let’s review each of these rendering methods, highlighting when and why you’d choose one over the other.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSG (Static Site Generation)
&lt;/h3&gt;

&lt;p&gt;SSG generates HTML at build time, which can be served lightning-fast from a CDN. However, it’s not suitable for websites with frequently updated content. It’s also Next.js’s default rendering strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  ISR (Incremental Static Regeneration)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z93sss5advionc8cn9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z93sss5advionc8cn9y.png" alt=" " width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ISR is SSG’s flexible sibling. It allows content to be updated even after the initial build, making it perfect for websites that change occasionally but don’t require real-time data. Just add &lt;code&gt;export const revalidate = &amp;lt;value&amp;gt;&lt;/code&gt; to configure it per page, or use &lt;a href="https://nextjs.org/docs/canary/app/building-your-application/data-fetching/incremental-static-regeneration#on-demand-revalidation-with-revalidatepath" rel="noopener noreferrer"&gt;&lt;code&gt;revalidatePath&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://nextjs.org/docs/canary/app/building-your-application/data-fetching/incremental-static-regeneration#on-demand-revalidation-with-revalidatetag" rel="noopener noreferrer"&gt;&lt;code&gt;revalidateTag&lt;/code&gt;&lt;/a&gt; for more targeted revalidation.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSR (Server-Side Rendering)
&lt;/h3&gt;

&lt;p&gt;SSR renders pages on the server for each user request, meaning content is always fresh. It’s ideal for highly dynamic content, though it can be slower than SSG since pages are generated on-demand. SSR shines in scenarios where up-to-date content matters but client-side interactivity isn’t crucial.&lt;/p&gt;

&lt;h3&gt;
  
  
  PPR (Progressive Page Rendering)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy24m3t97fitz51tyg0x6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy24m3t97fitz51tyg0x6.png" alt=" " width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/partial-prerendering" rel="noopener noreferrer"&gt;PPR introduces a hybrid approach&lt;/a&gt;. It operates on the component level instead of the page level, making it unique. A static SSR shell serves initially, while dynamic content streams in as components wrapped in Suspense load asynchronously. This lets you mix and match SSR and CSR on the same page, serving a static shell immediately and gradually populating it with interactive content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And that’s the roundup! Each rendering strategy offers distinct advantages depending on your application’s requirements. Play around, experiment, and find the best fit for your use case!&lt;br&gt;
Happy coding!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Credits: Done based on the JS Mastery resources and with a touch of AI formatting&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>New in WebDev 2024 - Interactive Experiences</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Fri, 09 Aug 2024 09:32:50 +0000</pubDate>
      <link>https://dev.to/hugaidas/new-in-webdev-2024-interactive-experiences-25c4</link>
      <guid>https://dev.to/hugaidas/new-in-webdev-2024-interactive-experiences-25c4</guid>
      <description>&lt;p&gt;Recently we had a chance to witness an amazing &lt;a href="https://io.google/2024/" rel="noopener noreferrer"&gt;Google I/O conference&lt;/a&gt; which surprised devs with a bunch of so-needed updates in web development. Today we will briefly go through some juiciest features that you can already use in your apps or that will be available in the near future. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frizhosv2jyb56zm9gzi8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frizhosv2jyb56zm9gzi8.png" alt="My precious meme" width="600" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New Interactice Experiences you should know about
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Scroll-driven animations
&lt;/h3&gt;

&lt;p&gt;WebPlatform status - &lt;a href="https://webstatus.dev/features/scroll-driven-animations?q=Scroll-driven" rel="noopener noreferrer"&gt;Limited Availability&lt;/a&gt;.&lt;br&gt;
Safari and Firefox still do not support this feature yet, but they are pretty close to it.&lt;/p&gt;

&lt;p&gt;No more GSAP and Framer motion, no heavy client-side javascript, on top of all, these animations have great tooling and &lt;a href="https://scroll-driven-animations.style/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0ujgz7ozulunlfzq127.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0ujgz7ozulunlfzq127.gif" alt="scroll-driven animations website" width="600" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though this is a relatively new feature, we have a set of nice dev tools to debug scroll-driven animations, and all animations in general. I think this is one of the biggest advantages of this new feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qxzdud4utu0s13px8rz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7qxzdud4utu0s13px8rz.gif" alt="devtools for animations" width="700" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F514olgeftisabgdxy23y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F514olgeftisabgdxy23y.gif" alt="devtools for animations - scroll-driven" width="600" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can integrate it using polyfill: &lt;a href="https://github.com/flackr/scroll-timeline" rel="noopener noreferrer"&gt;from this repo&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Same-document view transitions for single-page applications
&lt;/h3&gt;

&lt;p&gt;WebPlatform status - &lt;a href="https://webstatus.dev/features/view-transitions?q=view+transitions" rel="noopener noreferrer"&gt;Limited Availability&lt;/a&gt;. &lt;br&gt;
Safari and Firefox do not support it well.&lt;/p&gt;

&lt;p&gt;Already well-known young solution for SPA transitions, a huge field to experiment and explore. Comes with a dedicated dev tool as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnne3hx9d5n25ketth4c9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnne3hx9d5n25ketth4c9.gif" alt="SPA View Transitions Demo" width="720" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a view transition runs on a single document it is called a same-document view transition. This is typically the case in single-page applications (SPAs) where JavaScript is used to update the DOM. Same-document view transitions are supported in Chrome as of Chrome 111.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  How it works
&lt;/h4&gt;

&lt;p&gt;When invoked, the browser automatically captures snapshots of all elements that have a view-transition-name CSS property declared on them.&lt;/p&gt;

&lt;p&gt;It then executes the passed in callback that updates the DOM, after which it takes snapshots of the new state.&lt;/p&gt;

&lt;p&gt;These snapshots are then arranged in a tree of pseudo-elements and animated using the power of CSS animations. Pairs of snapshots from the old and new state smoothly transition from their old position and size to their new location, while their content crossfades. If you want, you can use CSS to customize the animations. &lt;/p&gt;

&lt;p&gt;You can read more: &lt;a href="https://developer.chrome.com/docs/web-platform/view-transitions/same-document#:~:text=When%20a%20view%20transition%20runs,Chrome%20as%20of%20Chrome%20111." rel="noopener noreferrer"&gt;in this article&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. View Transition CSS classes
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Up until now, when animating multiple snapshots in the same way, you needed to target each and every snapshot individually by repeating its pseudo-selector for every element that has a unique view-transition-name.&lt;br&gt;
With view-transition-class you can now add a shared name to all snapshots. Use this shared name in the pseudo selectors to target all snapshots that match. This results in far simpler selectors, which automatically scale from one to many elements.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#cards-wrapper &amp;gt; div {
  view-transition-class: card;
}
html::view-transition-group(.card) {
  animation-timing-function: var(--bounce);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbn8hrksdo9i7l70irykg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbn8hrksdo9i7l70irykg.gif" alt="Demo View Transitions CSS clsses" width="700" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7skwgksd4sogd7fb11c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7skwgksd4sogd7fb11c.png" alt="Browser support for view transition CSS classes" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More on this: &lt;a href="https://developer.chrome.com/blog/view-transitions-update-io24#view-transition-class" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. View Transition types
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Before active types, you could add classes to the DOM and respond to those classes in your CSS. However, you'd also have to cleanup after the transitions were complete.&lt;br&gt;
With view transition types you can achieve the same result, with the added benefit of these types automatically getting cleaned up once the view transition has finished. Types only apply when capturing or performing the transition.&lt;br&gt;
For same-document view transitions, pass the types into the startViewTransition method which now accepts an object. update is the callback function that updates the DOM, and types is a sequence of strings.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For example, you can animate your pagination like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const direction = determineBackwardsOrForwards();

const t = document.startViewTransition({
  update: updateTheDOMSomehow,
  types: ['slide', direction],
}););
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqj3mkqllkijptcxh7itx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqj3mkqllkijptcxh7itx.gif" alt="Demo view transition types" width="700" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To play around and explore more: &lt;a href="https://developer.chrome.com/blog/view-transitions-update-io24#view-transition-types" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Cross-document view transitions
&lt;/h3&gt;

&lt;p&gt;Last but not least, it is a multi-page application of view transitions! This was the most exciting update in my opinion. &lt;/p&gt;

&lt;h4&gt;
  
  
  TL;DR:
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;What's different when compared with same-document view transitions, is that with cross-document view transitions you don't need to call document.startViewTransition to start a view transition. Instead, the trigger for a cross-document view transition is a same-origin navigation from one page to another, an action that is typically performed by the user of your website clicking a link.&lt;br&gt;
In other words, there is no API to call in order to start a view transition between two documents. However, there are two conditions that need to be fulfilled:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Both documents need to exist on the same origin.&lt;/li&gt;
&lt;li&gt;Both pages need to opt-in to allow the view transition.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to dive deeper into it, I highly recommend watching &lt;a href="https://www.youtube.com/watch?v=eY6C_-aDdTo" rel="noopener noreferrer"&gt;this 15-minute video from the conference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Demo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuqczfrnu2uy90dy3m1y.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiuqczfrnu2uy90dy3m1y.gif" alt="Cross Document Transitions demo" width="700" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// OLD PAGE LOGIC
window.addEventListener('pageswap', async (e) =&amp;gt; {
  if (e.viewTransition) {
    const targetUrl = new URL(e.activation.entry.url);

    // Navigating to a profile page
    if (isProfilePage(targetUrl)) {
      const profile = extractProfileNameFromUrl(targetUrl);

      // Set view-transition-name values on the clicked row
      document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
      document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';

      // Remove view-transition-names after snapshots have been taken
      // (this to deal with BFCache)
      await e.viewTransition.finished;
      document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
      document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
    }
  }
});

// NEW PAGE LOGIC
window.addEventListener('pagereveal', async (e) =&amp;gt; {
  if (e.viewTransition) {
    const fromURL = new URL(navigation.activation.from.url);
    const currentURL = new URL(navigation.activation.entry.url);

    // Navigating from a profile page back to the homepage
    if (isProfilePage(fromURL) &amp;amp;&amp;amp; isHomePage(currentURL)) {
      const profile = extractProfileNameFromUrl(currentURL);

      // Set view-transition-name values on the elements in the list
      document.querySelector(`#${profile} span`).style.viewTransitionName = 'name';
      document.querySelector(`#${profile} img`).style.viewTransitionName = 'avatar';

      // Remove names after snapshots have been taken
      // so that we're ready for the next navigation
      await e.viewTransition.ready;
      document.querySelector(`#${profile} span`).style.viewTransitionName = 'none';
      document.querySelector(`#${profile} img`).style.viewTransitionName = 'none';
    }
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, as usual, here are the docs to learn more: &lt;a href="https://developer.chrome.com/docs/web-platform/view-transitions/cross-document" rel="noopener noreferrer"&gt;Chrome docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;That covers everything I wanted to share with you. Of course, there are many more smaller updates that enhance the overall user experience, but I'm confident that the five mentioned above will soon become the standard.&lt;/p&gt;

&lt;p&gt;So explore, experiment, and adopt!&lt;/p&gt;

&lt;p&gt;Happy coding, everyone!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>BaseLine - a reliable source of truth for a Web developer</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Tue, 11 Jun 2024 13:12:02 +0000</pubDate>
      <link>https://dev.to/hugaidas/baseline-a-reliable-source-of-truth-for-a-web-developer-1jfj</link>
      <guid>https://dev.to/hugaidas/baseline-a-reliable-source-of-truth-for-a-web-developer-1jfj</guid>
      <description>&lt;p&gt;Browsing MDN docs you might encountered this widget:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sjc0938ef2khhm3up29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9sjc0938ef2khhm3up29.png" alt=" " width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But what does it actually mean and why should you trust it?&lt;br&gt;
Let's figure that out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;With the web platform constantly evolving and browsers undergoing rapid innovation, developers find it challenging to keep pace with the changes. Moreover, there's a lack of a shared vocabulary for discussing commonly available web features.&lt;/p&gt;

&lt;p&gt;One of the solutions to address this issue became BaseLine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definition
&lt;/h2&gt;

&lt;p&gt;Official definition is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Baseline identifies web platform features that work across browsers. Baseline helps you decide when to use a feature by telling you when it is less likely to cause compatibility problems for your site's visitors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A Baseline feature, whether it's an API, a group of CSS properties, or a JavaScript syntax, functions reliably across numerous popular desktop and mobile browsers like Chrome, Edge, Firefox, and Safari.&lt;/p&gt;

&lt;p&gt;These features are characterized as either newly accessible in the latest stable browsers or as widely available with ongoing support across different versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Badges Concept
&lt;/h2&gt;

&lt;p&gt;Basically, BaseLine is presented as a set of widgets where each of them has a specific meaning:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfjei8y95gjzzn3by92v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjfjei8y95gjzzn3by92v.png" alt=" " width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you see a widely available Baseline badge, then you can trust that the feature has a consistent history of support in each of the Baseline browsers. A widely available feature has been in multiple browsers for years. It works with many browsers and devices, even ones that aren't yet up to date with the latest browser releases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl700uxststfor2wkjxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl700uxststfor2wkjxr.png" alt=" " width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you see a newly available Baseline badge, then you can trust that the feature works in at least the latest stable version of each of the Baseline browsers and often more. A newly available feature works in the latest browsers, but may not work with older browsers and devices. Consider your site's audience carefully before using a newly available feature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3lpm3wa27jahy9g9eh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6g3lpm3wa27jahy9g9eh.png" alt=" " width="800" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you see a limited availability badge, then that feature is not Baseline. Do more research and testing with your site's users before relying on that feature, or wait for it to become Baseline.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Browser support
&lt;/h2&gt;

&lt;p&gt;According to the documentation at the time of publishing this article, Baseline tracks availability with the following browsers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apple Safari (iOS)&lt;/li&gt;
&lt;li&gt;Apple Safari (macOS)&lt;/li&gt;
&lt;li&gt;Google Chrome (Android)&lt;/li&gt;
&lt;li&gt;Google Chrome (desktop)&lt;/li&gt;
&lt;li&gt;Microsoft Edge (desktop)&lt;/li&gt;
&lt;li&gt;Mozilla Firefox (Android)&lt;/li&gt;
&lt;li&gt;Mozilla Firefox (desktop)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What About CanIUse?
&lt;/h2&gt;

&lt;p&gt;We do have a great tool such as &lt;a href="https://caniuse.com/" rel="noopener noreferrer"&gt;CanIUse&lt;/a&gt; and of course, BaseLine is not going to replace it. &lt;/p&gt;

&lt;p&gt;Baseline serves as a general reference for support and may not address every scenario. If your website must function with older devices or browser versions not included in the Baseline status, you might need to conduct your own research or testing.&lt;/p&gt;

&lt;p&gt;If Baseline doesn't fit your needs, you must consult with &lt;a href="https://caniuse.com/" rel="noopener noreferrer"&gt;CanIUse&lt;/a&gt; before using a feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I am excited about how the community is becoming more and more united and we have so many different tools to get rid of the confusion and make as less mistakes as possible. BaseLine is a trustworthy source and I believe that it is only going to improve.&lt;/p&gt;

&lt;p&gt;I hope now you understand a little bit more about it and might find it practical in your daily work.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Baseline/Compatibility" rel="noopener noreferrer"&gt;Glossary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/blog/baseline-evolution-on-mdn/" rel="noopener noreferrer"&gt;Evolution on MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>React Compiler - New Hero?</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Thu, 16 May 2024 14:35:49 +0000</pubDate>
      <link>https://dev.to/hugaidas/react-compiler-new-hero-5b21</link>
      <guid>https://dev.to/hugaidas/react-compiler-new-hero-5b21</guid>
      <description>&lt;p&gt;Have you seen the first day of React Conf 2024? Were you as excited as I am about new changes? I personally liked that they made &lt;code&gt;ref&lt;/code&gt; as a component prop and we finally can get rid of forwardRef!&lt;/p&gt;

&lt;p&gt;But the true GEM, that was shining the most, definitely was a React Compiler!&lt;/p&gt;

&lt;p&gt;Let's dive a bit deeper into it!&lt;/p&gt;

&lt;p&gt;For those who want a short overview, here it is:&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React Compiler provides memoization under the hood&lt;/li&gt;
&lt;li&gt;It's Opensource!&lt;/li&gt;
&lt;li&gt;No need to use hooks like &lt;code&gt;useMemo&lt;/code&gt; and &lt;code&gt;useCallback&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Not stable yet, you can experiment but do not use it in production. Give it some time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for those who want to know the details, I am here to spill the tea!&lt;/p&gt;

&lt;h2&gt;
  
  
  How React Compiler works under the hood
&lt;/h2&gt;

&lt;p&gt;Here is a short chart of what happens initially:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1c3kgsv4segt3gmd3m6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy1c3kgsv4segt3gmd3m6.png" alt=" " width="321" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's how we get our optimization and we do not need &lt;code&gt;useMemo&lt;/code&gt; or &lt;code&gt;useCallback&lt;/code&gt; anymore&lt;/p&gt;

&lt;p&gt;But when our memoCache is ready, what happens? Here is another chart to demonstrate the process, which is quite simple:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqczjy6h4jc5w728mn8ub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqczjy6h4jc5w728mn8ub.png" alt=" " width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But it is important to remember, that React Compiler is not part of React 19! It is a separate open-source project. And there is one little caveat here...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t30niksn7vt95iluktg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t30niksn7vt95iluktg.png" alt=" " width="775" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we should expect a small headache soon when React Compiler gains mass adoption.&lt;/p&gt;

&lt;p&gt;One interesting thing I have found - under the hood there is lots and lots of typescript! What does it mean to us? Less bugs, better support, and documentation. I believe TS is a must in modern web development and was happy to see it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4vdn3j5gvpozx85rwda.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4vdn3j5gvpozx85rwda.jpeg" alt=" " width="800" height="709"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatability and fallback
&lt;/h2&gt;

&lt;p&gt;React Compiler has a fallback for the bad-written code. Besides that additional linter comes along with the Compiler. If the compilation is going to damage the component, the Compiler falls back on the original transpiler and everything still works. But if you follow the main &lt;a href="https://react.dev/reference/rules" rel="noopener noreferrer"&gt;React Rules&lt;/a&gt;, you will not have any bad side effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about useEffect?
&lt;/h2&gt;

&lt;p&gt;Unfortunately, the dependencies array for &lt;code&gt;useEffect&lt;/code&gt; is still necessary, but React Compiler helps to stabilize the non-primitive references in your dependencies array. And again, it is just better to follow &lt;a href="https://react.dev/reference/rules" rel="noopener noreferrer"&gt;React Rules&lt;/a&gt; so you do not need this stabilization at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Since this tool is still in its yearly age, you can freely experiment with it, but be careful or better not use it in production, give it some time to be more stable and resolve current issues.&lt;/p&gt;

&lt;p&gt;There is a public &lt;a href="https://github.com/facebook/react/pull/29061" rel="noopener noreferrer"&gt;React Compiler PR&lt;/a&gt;, if you are interested, go check it out, and maybe leave a supportive comment to the community and devs. It feels like a historical moment, one small step forward!&lt;/p&gt;

&lt;p&gt;That's all for now, thank you for your time, and happy coding!&lt;/p&gt;

&lt;p&gt;Materials and references:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=PYHBHK37xlE&amp;amp;ab_channel=JackHerrington" rel="noopener noreferrer"&gt;React Compiler: In-Depth Beyond React Conf 2024&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://playground.react.dev/#N4Igzg9grgTgxgUxALhAgHgBwjALgAgBMEAzAQygBsCSoA7OXASwjvwFkBPAQU0wAoAlPmAAdNvhgJcsNgB5CTAG4A+ABIJKlCPgDqOSoTkB6RaoDc4gL7iQVoA" rel="noopener noreferrer"&gt;React Compiler Playground by Meta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>react</category>
    </item>
    <item>
      <title>Integrate Gnosis Safe into your React Web3 App</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Tue, 23 Apr 2024 17:19:36 +0000</pubDate>
      <link>https://dev.to/hugaidas/integrate-gnosis-safe-into-your-react-web3-app-33gp</link>
      <guid>https://dev.to/hugaidas/integrate-gnosis-safe-into-your-react-web3-app-33gp</guid>
      <description>&lt;p&gt;Recently, I had a chance to work on an interesting task where I needed to integrate the &lt;a href="https://safe.global/" rel="noopener noreferrer"&gt;Gnosis Safe&lt;/a&gt; multi-signature wallet into the existing application.&lt;/p&gt;

&lt;p&gt;I will walk you through a short tutorial, and I hope it will help you save a few hours of development. Let's begin.&lt;/p&gt;

&lt;p&gt;First of all, we should start with the official documentation for their &lt;a href="https://docs.safe.global/sdk/api-kit" rel="noopener noreferrer"&gt;API SDK&lt;/a&gt;. &lt;br&gt;
You can also explore what Gnosis Safe provides for developers, but in the context of our tutorial, we are going to keep it simple.&lt;/p&gt;

&lt;p&gt;You need to have already created a Gnosis Safe wallet with several addresses added as signers. The process is quite simple, so we also won't focus on this.&lt;/p&gt;

&lt;p&gt;According to the documentation, the first step is to install an SDK. I will use yarn, but feel free to use any other package manager.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add @safe-global/api-kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we need to create an EthAdapter based on the library you are using in your app. I will use ethers.js 6.12&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Depending on the library used by the dapp, there are two options:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/safe-global/safe-core-sdk/tree/main/packages/protocol-kit/src/adapters/ethers" rel="noopener noreferrer"&gt;Create an EthersAdapter instance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/safe-global/safe-core-sdk/tree/main/packages/protocol-kit/src/adapters/web3" rel="noopener noreferrer"&gt;Create a Web3Adapter instance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the instance of EthersAdapter or Web3Adapter is created, it can be used in the initialization of the API Kit.&lt;/p&gt;

&lt;p&gt;Here is the trick. The documentation tells you to use a private key to instantiate a wallet, but you can just use a signer from the provider.&lt;/p&gt;

&lt;p&gt;I created a TS file in a 'gnosis' folder, called it 'adapters.ts':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let signer = null;

let provider;

if (window.ethereum == null) {
    // If MetaMask is not installed, we use the default provider,
    // which is backed by a variety of third-party services (such
    // as INFURA). They do not have private keys installed,
    // so they only have read-only access
    console.log("MetaMask not installed; using read-only defaults");
    provider = ethers.getDefaultProvider();
} else {
    // Connect to the MetaMask EIP-1193 object. This is a standard
    // protocol that allows Ethers access to make all read-only
    // requests through MetaMask.
    provider = new ethers.BrowserProvider(window.ethereum);

    // It also provides an opportunity to request access to write
    // operations, which will be performed by the private key
    // that MetaMask manages for the user.
    signer = await provider.getSigner();
}

export const ethAdapter = new EthersAdapter({
    ethers,
    signerOrProvider: signer || provider,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you might encounter an error from Webpack about global await, just enable this experimental feature in your webpack config. You can use &lt;a href="https://www.npmjs.com/package/react-app-rewired" rel="noopener noreferrer"&gt;react-app-rewired&lt;/a&gt; to adjust your webpack configuration.&lt;/p&gt;

&lt;p&gt;After we have created ethAdapter, we can proceed and create the apiKit instance, which is literally a few lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const apiKit = new SafeApiKit({
    chainId: ethers.toBigInt(process.env.REACT_APP_CHAIN_ID as string),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full file for this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { EthersAdapter } from "@safe-global/protocol-kit";
import SafeApiKit from "@safe-global/api-kit";
import { ethers } from "ethers";

let signer = null;

let provider;

if (window.ethereum == null) {
    // If MetaMask is not installed, we use the default provider,
    // which is backed by a variety of third-party services (such
    // as INFURA). They do not have private keys installed,
    // so they only have read-only access
    console.log("MetaMask not installed; using read-only defaults");
    provider = ethers.getDefaultProvider();
} else {
    // Connect to the MetaMask EIP-1193 object. This is a standard
    // protocol that allows Ethers access to make all read-only
    // requests through MetaMask.
    provider = new ethers.BrowserProvider(window.ethereum);

    // It also provides an opportunity to request access to write
    // operations, which will be performed by the private key
    // that MetaMask manages for the user.
    signer = await provider.getSigner();
}

export const ethAdapter = new EthersAdapter({
    ethers,
    signerOrProvider: signer || provider,
});

export const apiKit = new SafeApiKit({
    chainId: ethers.toBigInt(process.env.REACT_APP_CHAIN_ID as string),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can start building our transaction factory. I created a separate file called 'transactions.ts':&lt;/p&gt;

&lt;p&gt;We need to propose a transaction to service and need to start from instantiating a protocolKit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const protocolKit = await Safe.create({
    ethAdapter,
    safeAddress: process.env.REACT_APP_GNOSIS_SAFE_ADDRESS as string,
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we create a reusable function to prepare a transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function createSafeTransaction(to: string, value: string, data: string) {
    return protocolKit.createTransaction({
        transactions: [
            {
                to,
                value,
                data,
            },
        ],
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;UPD: If you are facing an issue with a conflicting &lt;code&gt;nonce&lt;/code&gt;, try to add the following by utilizing API Kit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const nextNonce = await apiKit.getNextNonce(process.env.REACT_APP_GNOSIS_SAFE_ADDRESS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then include it as an option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    return protocolKit.createTransaction({
        transactions: [
            {
                to,
                value,
                data,
            },
        ],
        options: {
            nonce: nextNonce,
        },
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next step we create a function for a proposal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function proposeTransaction(safeTransaction: SafeTransaction, signer: ethers.Signer) {
    console.log("Proposing transaction");
    const senderAddress = await signer.getAddress();
    const safeTxHash = await protocolKit.getTransactionHash(safeTransaction);
    const signature = await protocolKit.signHash(safeTxHash);

    return await apiKit.proposeTransaction({
        safeAddress: await protocolKit.getAddress(),
        safeTransactionData: safeTransaction.data,
        safeTxHash,
        senderAddress,
        senderSignature: signature.data,
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And finally, the transaction itself. Pay attention here, that we need to encode a transaction function call with the right params. If you use ethers.js, you can check out &lt;a href="https://docs.ethers.org/v5/api/utils/abi/interface/#Interface--encoding" rel="noopener noreferrer"&gt;documentation explaining how it works&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function safeBorrowRegionalPool(amount: string, signer: ethers.Signer, poolId: string, decimals: number = 6) {
    const CONTRACT_POOL_FACTORY = process.env.REACT_APP_CONTRACT_POOL_FACTORY!;
    const poolFactory = new ethers.Contract(CONTRACT_POOL_FACTORY, abiPoolFactory, signer);
    let poolAddress = await poolFactory.pools(poolId);
    const abi_interface = new ethers.Interface(abiRegionalPool);
    const parsedAmount = ethers.parseUnits(amount, decimals);
    const signerAddress = await signer.getAddress();

    const encodedFunctionCall = abi_interface.encodeFunctionData("borrow", [signerAddress, parsedAmount]);

    const safeTransaction = await createSafeTransaction(poolAddress, "0", encodedFunctionCall);
    return await proposeTransaction(safeTransaction, signer);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can finally call the function!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const signer = provider?.getSigner();
 safeBorrowRegionalPool(drawdownAmount.toString(), signer, 
 poolId as string, decimals).then((res) =&amp;gt; {
  console.log("Gnosis Safe Transaction created successfully!");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what is happening when we call it? Let's see...&lt;/p&gt;

&lt;p&gt;Metamask asks to confirm the transaction (our proposal):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbdgur962ydp13wyph5m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbdgur962ydp13wyph5m.png" alt=" " width="714" height="1052"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can see that the transaction appeared in the wallet's queue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2gzcw2p1rkrljhb7wr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2gzcw2p1rkrljhb7wr1.png" alt=" " width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can go even further and retrieve pending transactions from SDK, and confirm it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const safeTxHash = transaction.transactionHash
const signature = await protocolKit.signHash(safeTxHash)

// Confirm the Safe transaction
const signatureResponse = await apiKit.confirmTransaction(safeTxHash, signature.data)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can explore full references for &lt;a href="https://docs.safe.global/sdk/api-kit/reference#reference" rel="noopener noreferrer"&gt;all available methods here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That's all. &lt;br&gt;
Now your web3 application is type-safe and protected by a multi-signature wallet.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Bug of the month: Cannot convert a BigInt value to a number</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Tue, 02 Apr 2024 14:17:57 +0000</pubDate>
      <link>https://dev.to/hugaidas/bug-of-the-month-cannot-convert-a-bigint-value-to-a-number-2881</link>
      <guid>https://dev.to/hugaidas/bug-of-the-month-cannot-convert-a-bigint-value-to-a-number-2881</guid>
      <description>&lt;p&gt;Hello Everyone,&lt;/p&gt;

&lt;p&gt;I encountered a puzzling bug while deploying my web3 application to production. If you're familiar with web3 frontend libraries and browser plugins like MetaMask, you might find this interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem:
&lt;/h2&gt;

&lt;p&gt;Upon deployment, I faced an unexpected error:&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught TypeError: Cannot convert a BigInt value to a number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It functioned perfectly on my local machine but caused a crash in the live environment.&lt;/p&gt;

&lt;p&gt;Let's troubleshoot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Could it be a configuration problem during deployment?&lt;br&gt;
No, the local build works smoothly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Perhaps there's an issue with the configuration settings?&lt;br&gt;
No, they're all set correctly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq5hwuu9ax7lu41eekws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnq5hwuu9ax7lu41eekws.png" alt=" " width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a thorough investigation, I discovered the real culprit: browser support!&lt;/p&gt;

&lt;p&gt;The error arises because the production build of React doesn't specify browser versions. Instead, it uses default configurations, leading to the error.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution:
&lt;/h2&gt;

&lt;p&gt;Simply update your package.json file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"browserslist": {
    "production": [
      "supports bigint",
      "not dead"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this adjustment, your app should run smoothly in production.&lt;/p&gt;

&lt;p&gt;Feel free to reach out if you have any questions.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>bug</category>
    </item>
    <item>
      <title>Bring your TypeScript to the next level</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Mon, 18 Mar 2024 07:38:29 +0000</pubDate>
      <link>https://dev.to/hugaidas/bring-your-typescript-to-the-next-level-217f</link>
      <guid>https://dev.to/hugaidas/bring-your-typescript-to-the-next-level-217f</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqreufoy1h6xw747yblk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqreufoy1h6xw747yblk.jpg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With all my love for TypeScript, it has some annoying parts that you have to work around with custom solutions, type-checks, and functions. Which eventually can become very tedious and unmaintainable, and I did not know about any other solution to avoid it.&lt;/p&gt;

&lt;p&gt;As a big fan of TypeScript, I am following Matt Pococ, the best TS dev I know, he worked at XState and Vercel and now creates lots of educational content about TS for a living. By exploring his free articles I discovered that he is the creator of a useful library called &lt;a href="https://www.totaltypescript.com/ts-reset" rel="noopener noreferrer"&gt;TS Reset&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is not an Ad or any sort of promotion. I genuinely like his content and this library specifically. &lt;/p&gt;

&lt;p&gt;What the description says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Without ts-reset:&lt;/strong&gt;&lt;br&gt;
🚨 .json (in fetch) and JSON.parse both return any&lt;br&gt;
🤦 .filter(Boolean) doesn't behave how you expect&lt;br&gt;
😡 array.includes often breaks on readonly arrays&lt;br&gt;
ts-reset smooths over these hard edges, just like a CSS reset does in the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With ts-reset:&lt;/strong&gt;&lt;br&gt;
👍 .json (in fetch) and JSON.parse both return unknown&lt;br&gt;
✅ .filter(Boolean) behaves EXACTLY how you expect&lt;br&gt;
🥹 array.includes is widened to be more ergonomic&lt;br&gt;
🚀 And several more changes!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this is one of the examples how to use it and what it does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import in a single file, then across your whole project...
import '@total-typescript/ts-reset'
// .filter just got smarter!
const filteredArray = [1, 2, undefined].filter(Boolean) // number[]
// Get rid of the any's in JSON.parse and fetch
const result = JSON.parse('{}') // unknown
fetch('/')
  .then((res) =&amp;gt; res.json())
  .then((json) =&amp;gt; {
    console.log(json) // unknown
  })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out &lt;a href="https://www.totaltypescript.com/ts-reset" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; to learn more. &lt;br&gt;
I am going to use this in my future projects by default for sure, it looks awesome and can save lots of time with guaranteed type safety. Try it out and decide if it suits you as well!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>The difference between framework and library in JavaScript</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Thu, 21 Dec 2023 13:50:36 +0000</pubDate>
      <link>https://dev.to/hugaidas/the-difference-between-framework-and-library-in-javascript-219i</link>
      <guid>https://dev.to/hugaidas/the-difference-between-framework-and-library-in-javascript-219i</guid>
      <description>&lt;p&gt;In the ever-evolving world of web development, the terms "framework" and "library" are frequently used, but often misunderstood. Grasping the difference is vital for making informed choices in project development. This article aims to demystify these concepts, using React and Next.js as prime examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvubxugtlf91g1kl8ei.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvubxugtlf91g1kl8ei.png" alt="nextjs vs react" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bother with understanding?
&lt;/h2&gt;

&lt;p&gt;Understanding whether to use a library or a framework affects how a project is structured, maintained, and scales over time. It influences the level of control developers have over their code and impacts the learning curve for new team members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries: A Peek into React
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73wim9rrpkf16jq9av0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73wim9rrpkf16jq9av0k.png" alt="meme react js" width="500" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s a Library?
&lt;/h3&gt;

&lt;p&gt;Think of a library like React as your toolkit. It's a collection of code snippets and components you can use to build your user interface. It doesn't tell you how to build your entire app, just gives you the tools you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  React’s Role
&lt;/h3&gt;

&lt;p&gt;React is fantastic for creating dynamic, high-performance user interfaces. It's like having a versatile tool that can be adapted to various tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros and Cons
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Great flexibility, a strong community, and a wealth of resources.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; It’s just a part of the puzzle. You’ll need other tools for things like state management and routing, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frameworks: Exploring Next.js
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l2lc536o4aq1oua2ipv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7l2lc536o4aq1oua2ipv.png" alt="meme next js" width="544" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What’s a Framework?
&lt;/h4&gt;

&lt;p&gt;A framework like Next.js is more encompassing. It not only gives you tools but also tells you how to use them. It’s like having a guidebook along with your toolkit.&lt;/p&gt;

&lt;h4&gt;
  
  
  Next.js’ Superpowers
&lt;/h4&gt;

&lt;p&gt;Built on React, Next.js adds features like server-side rendering and static site generation, which are super helpful for SEO and performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pros and Cons
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Offers a structured approach, built-in features for performance optimization, and is great for SEO.&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Less flexible than using a standalone library. You have to adhere to the framework's rules&lt;/p&gt;

&lt;p&gt;I want to quote one interesting thought with a small change from my side:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A note on being “opinionated”&lt;br&gt;
You’ll often hear frameworks and libraries described as “opinionated” or “un-opinionated.” These terms are subjective. They attempt to define the level of freedom a developer has when structuring their code.&lt;/p&gt;

&lt;p&gt;Frameworks are more opinionated than not since — by definition — the inversion of control requires a concession of application-design freedom.&lt;/p&gt;

&lt;p&gt;Again, the degree to which something is opinionated is subjective. For example, I personally would consider Angular a highly opinionated framework, and NextJS a less-opinionated framework.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Blending React and Next.js
&lt;/h3&gt;

&lt;p&gt;Combining React and Next.js harnesses the flexibility of React with the structured power of Next.js. It’s like having the freedom to experiment with your style while also having a go-to set of perfectly coordinated outfits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Whether you go for a library like React, or framework like Next.js, or a combination of both depends on your project needs and personal coding style. The library offers flexibility and freedom, perfect for when you want to experiment and create something unique. The Framework, on the other hand, is like having a roadmap, guiding you to build efficient, high-performance web applications with ease.&lt;/p&gt;

&lt;p&gt;So, keep exploring, and remember, the best tool is the one that fits your project's needs and your style as a developer. Stay updated and keep learning – the tech world is your oyster! 🌐👩‍💻&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/the-difference-between-a-framework-and-a-library-bd133054023f/" rel="noopener noreferrer"&gt;The Difference Between a Framework and a Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://slashdev.io/blog/why-is-react-a-library-and-next-js-a-framework-understanding-the-difference" rel="noopener noreferrer"&gt;Why Is React a Library and Next.js a Framework? Understanding the Difference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.itechempires.com/2023/03/javascript-library-vs-framework-understanding-the-differences-with-react-js-and-next-js-examples/" rel="noopener noreferrer"&gt;JavaScript Library vs Framework: Understanding the Differences (with React JS and Next JS Examples)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builtin.com/software-engineering-perspectives/react-framework" rel="noopener noreferrer"&gt;Why Is React a Library and Next.js a Framework?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hygraph.com/blog/nextjs-vs-react" rel="noopener noreferrer"&gt;The Difference between Next.js and React?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Anchor scroll at the bottom of the container with dynamic content</title>
      <dc:creator>Victoria</dc:creator>
      <pubDate>Fri, 17 Nov 2023 09:14:59 +0000</pubDate>
      <link>https://dev.to/hugaidas/anchor-scroll-at-the-bottom-of-the-container-with-dynamic-content-2knj</link>
      <guid>https://dev.to/hugaidas/anchor-scroll-at-the-bottom-of-the-container-with-dynamic-content-2knj</guid>
      <description>&lt;p&gt;This article serves as a short tutorial where I'll show you how to easily implement a somewhat tricky functionality.&lt;/p&gt;

&lt;p&gt;The case in question is a basic message box, where the latest content should appear at the bottom of the container, with the scroll anchored there.&lt;/p&gt;

&lt;p&gt;Here is our problem:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk0w0coogxeqzchlto89.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frk0w0coogxeqzchlto89.gif" alt="Problem" width="543" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Approach 1 - CSS only
&lt;/h2&gt;

&lt;p&gt;The simplest solution is to use a reversed flex column, which will cause the scroll to stick to the bottom:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6z2jb71j09eurdduputt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6z2jb71j09eurdduputt.gif" alt=" " width="600" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation in CSS:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Set the display of the container to flex.&lt;/li&gt;
&lt;li&gt;Use flex-direction: column-reverse; to start filling content from the bottom.&lt;/li&gt;
&lt;li&gt;Ensure your container has a set height and overflow: auto; to enable scrolling.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Approach 2 - Adding some JavaScript
&lt;/h2&gt;

&lt;p&gt;For automatic scrolling upon the addition of new content, you can tweak the smoothness to create the best user experience:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tqt8m4yv4ayc1k79xsc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tqt8m4yv4ayc1k79xsc.gif" alt=" " width="600" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation in React:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Use the useRef hook to maintain a reference to the container.&lt;/li&gt;
&lt;li&gt;Use the useEffect hook to detect changes in the content of the container.&lt;/li&gt;
&lt;li&gt;When new content is added, use the scrollIntoView method or adjust the scrollTop property to scroll to the bottom of the container.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const containerRef = useRef(null);

useEffect(() =&amp;gt; {
  const element = containerRef.current;
  if (element) {
    element.scrollTop = element.scrollHeight;
  }
}, [messages]); // assuming 'messages' is the state holding the chat content
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;Now you know two of the simplest ways to achieve a bottom-anchored scroll with dynamic content. If you have other methods or suggestions, please feel free to share them with me!&lt;/p&gt;

&lt;p&gt;You can also combine the two approaches mentioned and experiment with the smoothness of the scroll. You can find an example app &lt;a href="https://codesandbox.io/p/sandbox/divine-sun-n2fdqc?file=%2Fapp%2Fpage.tsx%3A46%2C42" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding and see you soon!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0jnwpp21oaci8g4f0hl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0jnwpp21oaci8g4f0hl.gif" alt=" " width="498" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
