<?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: Rayen Mabrouk</title>
    <description>The latest articles on DEV Community by Rayen Mabrouk (@rayenmabrouk).</description>
    <link>https://dev.to/rayenmabrouk</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%2F1309840%2F066dfe18-1f8c-472d-958c-2dc46231c834.png</url>
      <title>DEV Community: Rayen Mabrouk</title>
      <link>https://dev.to/rayenmabrouk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rayenmabrouk"/>
    <language>en</language>
    <item>
      <title>Why We Ditched Node for Bun in 2026 (And Why You Should Too)</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Thu, 08 Jan 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/why-we-ditched-node-for-bun-in-2026-and-why-you-should-too-48kg</link>
      <guid>https://dev.to/rayenmabrouk/why-we-ditched-node-for-bun-in-2026-and-why-you-should-too-48kg</guid>
      <description>&lt;p&gt;For years the JavaScript ecosystem felt like a settled landscape, Node was the undisputed king, Deno was the academic alternative, and "speed" was something we just accepted as "fast enough"&lt;/p&gt;

&lt;p&gt;But as we hit 2026, the baseline has shifted. We recently completed a full migration from Node to Bun for our all our repos. What started as an experiment ended as a permanent shift in our engineering culture.&lt;/p&gt;

&lt;p&gt;Here is why we made the leap and why 2026 is the year you should leave &lt;code&gt;node_modules&lt;/code&gt; headaches behind.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Death of the Toolchain Sprawl
&lt;/h3&gt;

&lt;p&gt;In the Node world, starting a project meant an immediate tax of configuration. You needed &lt;code&gt;npm&lt;/code&gt; for packages, &lt;code&gt;tsc&lt;/code&gt; for TypeScript, &lt;code&gt;jest&lt;/code&gt; or &lt;code&gt;vitest&lt;/code&gt; for testing, and &lt;code&gt;webpack&lt;/code&gt; or &lt;code&gt;esbuild&lt;/code&gt; for bundling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bun is a single binary that does all of it.&lt;/strong&gt;&lt;br&gt;
By switching to Bun, we deleted hundreds of lines of configuration files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Native TypeScript:&lt;/strong&gt; We no longer use &lt;code&gt;ts-node&lt;/code&gt; or &lt;code&gt;tsx&lt;/code&gt;. Bun runs &lt;code&gt;.ts&lt;/code&gt; files out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified Tooling:&lt;/strong&gt; &lt;code&gt;bun test&lt;/code&gt; is up to &lt;strong&gt;20x faster&lt;/strong&gt; than Jest and built-in. No more waiting 30 seconds for a test suite to initialize.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. ElysiaJS: The Bun Backend Framework
&lt;/h3&gt;

&lt;p&gt;The biggest catalyst for our migration was choosing ElysiaJS as our main backend framework.&lt;/p&gt;

&lt;p&gt;Elysia is a Bun-first framework designed specifically to leverage Bun's low-level performance. Since it’s optimized for the JavaScriptCore engine, the throughput is staggering.&lt;/p&gt;

&lt;p&gt;End-to-End Type Safety: With Elysia and Bun, types flow from the server to the client (via Eden Treaty) automatically. No more manual type synchronization!!&lt;/p&gt;

&lt;p&gt;The Speed Gap: In our benchmarks, Elysia on Bun handled over 250,000 requests/sec, making our old Express/Node services look like they were running in slow motion.&lt;/p&gt;

&lt;p&gt;Zero Overhead: Because Elysia is built on Web Standard APIs (Fetch, Request, Response), there is zero "framework tax."&lt;/p&gt;

&lt;p&gt;"With Bun + Elysia, we finally reached the 'Single Binary' dream. Our backend is now just one tool that handles everything from the database driver to the HTTP server."&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%2Fymy8t7954r9zwl2dpfzm.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%2Fymy8t7954r9zwl2dpfzm.png" alt=" " width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Performance That Actually Saves Money
&lt;/h3&gt;

&lt;p&gt;Benchmarks are one thing; cloud bills are another..&lt;br&gt;
In 2026, with the rise of edge computing and serverless architectures, &lt;strong&gt;startup time is currency.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Node.js (v23+)&lt;/th&gt;
&lt;th&gt;Bun (v1.3+)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cold Startup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~150ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~40ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP Requests/sec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~90k&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~125k&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Idle Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~95MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~65MB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;By switching our serverless functions to Bun, we reduced our execution duration by &lt;strong&gt;35%&lt;/strong&gt;, directly lowering our AWS Lambda costs. Bun’s use of the &lt;strong&gt;JavaScriptCore (JSC)&lt;/strong&gt; engine—the same tech powering Safari—prioritizes rapid start times over the heavy JIT (Just-In-Time) optimization overhead of Node's V8.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. "Bun Install" is the New Standard
&lt;/h3&gt;

&lt;p&gt;If you’ve ever waited 2 minutes for &lt;code&gt;npm install&lt;/code&gt;, &lt;code&gt;yarn install&lt;/code&gt;, or even &lt;code&gt;pnpm install&lt;/code&gt; to finish on a CI/CD pipeline, you know the pain. Bun’s package manager is roughly &lt;strong&gt;20x to 40x faster&lt;/strong&gt; than npm. It uses a binary lockfile (&lt;code&gt;bun.lockb&lt;/code&gt;) and global caching that makes dependency installation feel instantaneous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is the real deal, the speed diff is no joke here&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For our team, this meant our CI/CD pipelines went from 30-minute builds to under 5 minutes for our big monorepos.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. The 2026 Reality: Compatibility is No Longer an Issue
&lt;/h3&gt;

&lt;p&gt;The biggest argument against Bun in 2024 was "it doesn't support all npm packages." By 2026, that argument is dead. Bun now supports &lt;strong&gt;&amp;gt;95% of Node APIs&lt;/strong&gt;, including complex native modules like &lt;code&gt;buffer&lt;/code&gt;, &lt;code&gt;fs&lt;/code&gt;, and &lt;code&gt;path&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Following its acquisition by &lt;strong&gt;Anthropic&lt;/strong&gt;, Bun has reached a level of enterprise stability we hadn't seen before. It’s no longer just for "side projects"; it’s powering production-grade AI agents and high-concurrency APIs globally.&lt;/p&gt;




&lt;h3&gt;
  
  
  How to Start Your Migration
&lt;/h3&gt;

&lt;p&gt;You don't have to rewrite your whole app overnight. Start where we did:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Swap your Package Manager:&lt;/strong&gt; Run &lt;code&gt;bun install&lt;/code&gt; in your Node project. It’s a drop-in replacement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run your Tests:&lt;/strong&gt; Try &lt;code&gt;bun test&lt;/code&gt;. You'll see the speed difference immediately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migrate Scripts:&lt;/strong&gt; Change &lt;code&gt;node index.js&lt;/code&gt; to &lt;code&gt;bun index.ts&lt;/code&gt; in your &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  My Personal Thoughts..
&lt;/h3&gt;

&lt;p&gt;Node isn't "bad" but in 2026 it feels like using a heavy manual typewriter in a world of high-speed digital keyboards..&lt;br&gt;
Bun offers the performance, the developer experience, and the cost-savings that modern full-stack development demands.&lt;/p&gt;

&lt;p&gt;For the geeks reading this who want to see the cold, hard numbers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=_iEaaNIjg7U" rel="noopener noreferrer"&gt;Node vs Deno vs Bun: Performance &amp;amp; JavaScript runtime comparison&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This video provides a deep dive into 2026 performance benchmarks to help you visualize the raw speed differences between these runtimes.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Nx Architecture Guide</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Wed, 10 Sep 2025 15:54:05 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/nx-the-secret-sauce-big-tech-uses-to-build-scalable-monorepos-30c9</link>
      <guid>https://dev.to/rayenmabrouk/nx-the-secret-sauce-big-tech-uses-to-build-scalable-monorepos-30c9</guid>
      <description>&lt;h1&gt;
  
  
  Purpose &amp;amp; Principles
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; Build a &lt;strong&gt;scalable, maintainable monorepo&lt;/strong&gt; for TypeScript, React, Elysia.js ( or NestJS) — optimized for &lt;strong&gt;speed&lt;/strong&gt; and &lt;strong&gt;clarity&lt;/strong&gt; as the team and codebase grow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Guiding principles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single source of truth&lt;/strong&gt; for shared code → packages live in &lt;code&gt;/packages&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apps are independent&lt;/strong&gt;, only depend on packages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strict boundaries&lt;/strong&gt; enforced by Nx rules to prevent spaghetti dependencies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart automation&lt;/strong&gt; → generate, lint, build, and test only what changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer happiness&lt;/strong&gt; → fast feedback, consistent tooling, minimal cognitive overhead.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Why This Matters
&lt;/h1&gt;

&lt;p&gt;When multiple teams and apps share a codebase, things can &lt;strong&gt;spiral out of control&lt;/strong&gt; quickly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apps start depending on each other → deployment coupling and hidden breakage.&lt;/li&gt;
&lt;li&gt;Shared logic gets duplicated or inconsistently implemented.&lt;/li&gt;
&lt;li&gt;Build times explode as the repo grows.&lt;/li&gt;
&lt;li&gt;Onboarding new developers becomes painful — they don’t know &lt;em&gt;where code should live&lt;/em&gt; or &lt;em&gt;what’s safe to change&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following this structure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Independent apps&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;You can deploy, test, and scale each app without worrying about others.&lt;/li&gt;
&lt;li&gt;Example: Your LMS web app doesn’t break if someone changes the e-commerce backend.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single source of truth in &lt;code&gt;/packages&lt;/code&gt;&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Shared utilities, models, contracts, and UI components live in one place.&lt;/li&gt;
&lt;li&gt;No code duplication → no “bug fixed here but missed there”.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast pipelines with Nx caching&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Nx knows exactly which code depends on what → it only rebuilds and tests the minimal set of affected projects.&lt;/li&gt;
&lt;li&gt;This keeps CI and local dev &lt;em&gt;blazing fast&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  Problems This Solves
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;How This Doc Solves It&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Apps depend directly on each other&lt;/td&gt;
&lt;td&gt;Strict rule: Apps can &lt;strong&gt;only depend on packages&lt;/strong&gt;, never other apps.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code duplication across apps&lt;/td&gt;
&lt;td&gt;Centralize shared code in &lt;code&gt;/packages&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confusing folder structures&lt;/td&gt;
&lt;td&gt;Clear, predictable conventions for folder layout and naming.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slow builds &amp;amp; tests&lt;/td&gt;
&lt;td&gt;Nx affected graph + smart caching = only run what changed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fragile FE/BE type syncing&lt;/td&gt;
&lt;td&gt;Shared &lt;code&gt;contracts&lt;/code&gt; package with Zod → FE/BE stay type-safe.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Env chaos&lt;/td&gt;
&lt;td&gt;Clear rules for &lt;code&gt;.env&lt;/code&gt; handling and config packages.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New dev onboarding takes weeks&lt;/td&gt;
&lt;td&gt;Generators, clear docs, and tags → consistent, fast ramp-up.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  Workspace Layout
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apps/                  # Standalone deployable apps
 web/                 # React frontend (Next.js or Vite)
 admin/               # Admin dashboard
 marketing/           # Public marketing site
 mobile/              # React Native app
 api-nest/            # NestJS backend service
 api-scheduler/       # Background jobs service

packages/              # Reusable code (FE &amp;amp; BE)
 shared/
  util/              # Pure utility functions
  models/            # Shared TypeScript models
  contracts/         # Zod schemas + API contracts
lms/                 # LMS domain
 feature/           # State orchestration / hooks
 ui/                # UI components
 data-access/       # API clients or DB repositories 
 util/              # LMS-specific helpers
ecommerce/           # E-commerce domain
 feature/
 ui/
 data-access/
 util/
tools/                 # Custom Nx generators + scripts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Core Rules
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1 — Apps are &lt;strong&gt;Standalone&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Apps live in &lt;code&gt;/apps/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;They &lt;strong&gt;cannot&lt;/strong&gt; import anything from another app.&lt;/li&gt;
&lt;li&gt;They &lt;strong&gt;only import from &lt;code&gt;/packages&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;This ensures clean deployment boundaries and eliminates hidden coupling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example (✅ &lt;strong&gt;Allowed&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apps/web → imports → packages/lms-ui
apps/web → imports → packages/shared-contracts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example (❌ &lt;strong&gt;Forbidden&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apps/web → imports → apps/admin
apps/admin → imports → apps/api-nest

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2 — Packages Are the Source of Truth
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;All shared code lives in &lt;code&gt;/packages/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apps/&lt;/code&gt; are thin shells that glue together packages and runtime configuration.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Naming, Tags &amp;amp; Boundaries
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Package Naming
&lt;/h2&gt;

&lt;p&gt;Format: &lt;code&gt;&amp;lt;scope&amp;gt;-&amp;lt;type&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;scope&lt;/strong&gt; = domain (&lt;code&gt;lms&lt;/code&gt;, &lt;code&gt;ecommerce&lt;/code&gt;, &lt;code&gt;shared&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt; ∈ (&lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;ui&lt;/code&gt;, &lt;code&gt;data-access&lt;/code&gt;, &lt;code&gt;util&lt;/code&gt;, &lt;code&gt;models&lt;/code&gt;, &lt;code&gt;contracts&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;lms-ui&lt;/code&gt;, &lt;code&gt;lms-data-access&lt;/code&gt;, &lt;code&gt;shared-contracts&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Enforcing Boundaries with Nx
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.eslintrc.js&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;rules:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@nx/enforce-module-boundaries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;enforceBuildableLibDependency:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;allow:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;depConstraints:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"type:package"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type:ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"type:util"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"type:models"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"type:contracts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"scope:shared"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"scope:&amp;lt;same&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sourceTag"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"scope:shared"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"onlyDependOnLibsWithTags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"scope:shared"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Contracts &amp;amp; FE/BE Sync
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// packages/shared/contracts/course.ts&lt;/span&gt;
&lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;Course&lt;/span&gt; &lt;span class="o"&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;id&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;uuid&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;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="na"&gt;published&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;boolean&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Course&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;infer&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Course&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; use these schemas to type API clients and validate responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend (Nest or Elysia):&lt;/strong&gt; use schemas for input/output validation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Environment &amp;amp; Config Rules
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Apps own their &lt;code&gt;.env&lt;/code&gt; files.&lt;/li&gt;
&lt;li&gt;Packages &lt;strong&gt;must never&lt;/strong&gt; read directly from &lt;code&gt;process.env&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a &lt;code&gt;config&lt;/code&gt; package that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads env variables at runtime.&lt;/li&gt;
&lt;li&gt;Validates them with Zod.&lt;/li&gt;
&lt;li&gt;Exports a strongly-typed config object.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h1&gt;
  
  
  Caching, Targets &amp;amp; Bun
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1 — Default Targets (&lt;code&gt;nx.json&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"targetDefaults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typecheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"cache"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2 — Bun Commands
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun i                &lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
bun run nx serve web &lt;span class="c"&gt;# Run a frontend app&lt;/span&gt;
bun run nx serve api-nest &lt;span class="c"&gt;# Run backend&lt;/span&gt;
bun run nx affected &lt;span class="nt"&gt;-t&lt;/span&gt; lint,typecheck,test,build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Affected Workflow
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local Dev&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  bun run nx affected:graph
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before Commit&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  bun run nx affected -t lint,test,typecheck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CI&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bun run nx affected -t lint,typecheck,test,build --parallel&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Testing Strategy
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit tests&lt;/strong&gt; → close to source in &lt;code&gt;__tests__&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Component tests&lt;/strong&gt; → React Testing Library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E2E tests&lt;/strong&gt; → Playwright for apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contract tests&lt;/strong&gt; → Validate BE against Zod contracts.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Performance &amp;amp; DX Tips
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;barrel files&lt;/strong&gt; (&lt;code&gt;index.ts&lt;/code&gt;) to curate package exports.&lt;/li&gt;
&lt;li&gt;Keep packages small and domain-focused.&lt;/li&gt;
&lt;li&gt;Turn packages that need Node consumption into &lt;code&gt;buildable: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;tsup&lt;/code&gt; or &lt;code&gt;esbuild&lt;/code&gt; for &lt;strong&gt;tiny backend bundles&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Why Nx Over Competitors
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Nx&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Turborepo&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Lerna&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency graph&lt;/td&gt;
&lt;td&gt;✅ Auto&lt;/td&gt;
&lt;td&gt;❌ Manual&lt;/td&gt;
&lt;td&gt;❌ None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task scheduling &amp;amp; caching&lt;/td&gt;
&lt;td&gt;✅ Smart (local + remote)&lt;/td&gt;
&lt;td&gt;⚠️ Limited&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Built-in generators&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforceable boundaries&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Polyglot support (React, Elysia, Nest)&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;td&gt;⚠️ Limited&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remote caching (team-wide)&lt;/td&gt;
&lt;td&gt;✅ Built-in&lt;/td&gt;
&lt;td&gt;⚠️ Third-party&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  Quick Commands Cheat Sheet
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun run nx g @nx/js:lib lms-ui &lt;span class="nt"&gt;--directory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lms &lt;span class="nt"&gt;--tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"scope:lms,type:ui,platform:browser"&lt;/span&gt;
bun run nx graph
bun run nx affected &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;test
&lt;/span&gt;bun run nx serve web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Final Thoughts
&lt;/h1&gt;

&lt;p&gt;By enforcing these practices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each app remains &lt;strong&gt;deployable and testable on its own&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Shared logic lives in &lt;strong&gt;packages&lt;/strong&gt;, not copied between apps.&lt;/li&gt;
&lt;li&gt;Nx automatically keeps builds and tests &lt;strong&gt;fast&lt;/strong&gt; even as the codebase grows.&lt;/li&gt;
&lt;li&gt;The team has &lt;strong&gt;clear rules&lt;/strong&gt;, reducing onboarding friction and bugs.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Why We Ditched Drizzle &amp; Knex in favor of Kysely's Querybuilder</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Sat, 05 Apr 2025 07:46:17 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/why-we-ditched-drizzle-knex-in-favor-of-kyselys-querybuilder-2lgo</link>
      <guid>https://dev.to/rayenmabrouk/why-we-ditched-drizzle-knex-in-favor-of-kyselys-querybuilder-2lgo</guid>
      <description>&lt;p&gt;Building scalable applications often hinges on precise database interactions. While ORMs promise rapid development, they can obscure SQL and become bottlenecks as complexity grows. Even popular query builders like Knex and Drizzle present challenges. After navigating various projects, we found Kysely offered the best balance of control, maintainability, and crucially, end-to-end type safety.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: Balancing Abstraction and Control (The Pitfalls of Traditional ORMs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;The Illusion of Simplicity: Hidden Complexity&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ORMs abstract away SQL generation, which can be useful for simple operations. However, this abstraction conceals real database interactions, making it difficult to optimize queries or troubleshoot performance issues. Debugging queries often requires reverse engineering ORM-generated SQL, adding unnecessary complexity,&lt;br&gt;
this is very crucial when working with large scale complex apps that often require complex query logic.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. &lt;strong&gt;Limited Customization&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Many ORMs enforce strict patterns and conventions. When query requirements deviate from standard use cases whether for performance optimizations or non standard joins ORM constraints become a bottleneck. Developers often resort to workarounds, leading to convoluted, less maintainable code.. &lt;/p&gt;
&lt;h3&gt;
  
  
  3. &lt;strong&gt;The Spaghetti Code Scenario: Complex Queries in ORM Syntax&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For simple CRUD operations, ORM syntax is manageable. However, for queries involving multiple joins, subqueries, or aggregations, ORM APIs become cumbersome and difficult to follow. This not only makes debugging more challenging but also increases the risk of subtle errors, especially in production-grade systems, a nightmare to work with for new devs joining to project.&lt;/p&gt;
&lt;h2&gt;
  
  
  Type Safety: A Crucial Distinction
&lt;/h2&gt;

&lt;p&gt;A system is either type-safe or it isn't—there is no in-between. Partial type safety slows development by introducing misleading assurances that a query is correct when, in reality, it's &lt;strong&gt;not&lt;/strong&gt;. A truly type-safe query builder should catch errors at compile time rather than runtime, preventing incorrect table references and typos.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drizzle&lt;/strong&gt;, for example, gives the impression of type safety, but only applies type validation to query results not the queries themselves. This means you can still write invalid queries, much like with &lt;strong&gt;Knex&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kysely&lt;/strong&gt;, however, aims for stricter, end-to-end type safety. Its typings are designed to understand the query's structure, including aliases and subqueries, making it much harder to formulate logically incorrect joins or references that would only fail at runtime.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Kysely vs. Knex vs. Drizzle: A Practical Comparison
&lt;/h2&gt;

&lt;p&gt;To illustrate how Kysely improves query safety and maintainability, let's examine a real world SQL query involving subqueries and joins. The goal is to fetch a list of books along with the name of the last lender for each book.  &lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;SQL Query Representation&lt;/strong&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="nv"&gt;"books"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;"u"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"name"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"username"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;
  &lt;span class="nv"&gt;"books"&lt;/span&gt;
  &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt;
      &lt;span class="k"&gt;MAX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"last_lending_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;"lendings"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"book_id"&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt;
      &lt;span class="nv"&gt;"lendings"&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt;
      &lt;span class="nv"&gt;"book_id"&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"l"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"book_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"books"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;
  &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"lendings"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"l1"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"l1"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"l"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"last_lending_id"&lt;/span&gt;
  &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nv"&gt;"u"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"u"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"l1"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Knex Implementation: SQL-Like but Error-Prone&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Knex provides a SQL-like API but lacks type safety, making it prone to runtime errors due to typos or incorrect references.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;knex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;u.name as username&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;leftJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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="nx"&gt;query&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id as last_lending_id&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;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings.book_id&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="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings&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;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;book_id&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="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l&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;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l.book_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books.id&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="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings as l1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l1.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l.last_lending_id&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;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users as u&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;u.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l1.user_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the syntax is intuitive for SQL users, Knex does not provide static type validation. Mistakes such as referencing &lt;code&gt;l.book_id&lt;/code&gt; incorrectly will only be caught at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Drizzle Implementation: Improved Readability but Partial Type Safety&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Drizzle attempts to balance SQL-style query building with type safety but falls short in enforcing correctness during query construction.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;book_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lendings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;last_lending_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lendings&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;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;last_lending_id&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lendings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lendings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;l&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;l1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;aliasedTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lendings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;l1&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;u&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;aliasedTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;u&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&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;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&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="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;u&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="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;leftJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;book_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;books&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="nf"&gt;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l1&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="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_lending_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;u&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="nx"&gt;l1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Drizzle improves readability and provides type safety for results and basic query elements. However, notice how aliases (l, l1, u) are defined. While Drizzle types the result correctly, it doesn't inherently prevent runtime errors if you mistakenly used schema.lendings.id instead of l.last_lending_id in the later joins within the query construction. The types guide you, but the logical connection isn't always enforced at compile time in these complex cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Kysely Implementation: Fully Type-Safe and SQL-Like&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Kysely enforces strict type safety across the entire query-building process, preventing incorrect joins and typos at compile time.&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="nx"&gt;db&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selectFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books&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;leftJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eb&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;eb&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selectFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings&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;select&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sl&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="nx"&gt;sl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_lending_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings.book_id&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;book_id&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="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l&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="nx"&gt;join&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;join&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l.book_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books.id&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lendings as l1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l1.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l.last_lending_id&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;innerJoin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;users as u&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;u.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;l1.user_id&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;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;books.name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;u.name as username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kysely's strict typing shines here. The use of functions like (eb) =&amp;gt; eb.selectFrom(...) and (join) =&amp;gt; join.onRef(...) allows Kysely's types to track the available tables and columns within the current scope, including aliases from subqueries (l). Referencing l.book_id is type-checked against the subquery's output. Attempting to reference an invalid column or alias here would result in a compile-time TypeScript error, preventing runtime failures.&lt;/p&gt;

&lt;p&gt;Unlike &lt;strong&gt;Knex&lt;/strong&gt; and &lt;strong&gt;Drizzle&lt;/strong&gt;, Kysely ensures that every part of the query is type-checked, preventing errors before execution. Additionally, its API remains readable while enforcing correctness.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Takeaways: Why Kysely Stands Out&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Strict Type Safety&lt;/strong&gt;: Kysely prevents incorrect table references, column names, and joins at compile time, eliminating common runtime errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL-Like Query Construction&lt;/strong&gt;: While different from traditional SQL in ordering, Kysely's API ensures logical query composition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Yet Maintainable&lt;/strong&gt;: Kysely's API maps closely to SQL concepts while ensuring logical query construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoids the Pitfalls of ORMs&lt;/strong&gt;: Unlike ORMs, Kysely doesn’t obscure SQL execution, giving developers full control over performance optimizations.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion: Embrace Type-Safe Query Building&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While Knex offers flexibility and Drizzle provides a good step towards type safety, both can still allow subtle bugs in complex queries to reach runtime.&lt;br&gt;
Drizzle improves upon Knex by adding type safety to query results but falls short in enforcing correctness during query construction.  &lt;/p&gt;

&lt;p&gt;Kysely, on the other hand, achieves full end-to-end type safety while maintaining a SQL-like, flexible API. If your system demands precise control over database interactions and robust type validation, Kysely provides the clarity and safety needed for scalable, high-performance applications.  &lt;/p&gt;

&lt;p&gt;For us, adopting Kysely was a game changer, and for anything beyond simple prototypes, it's now our go-to choice.&lt;/p&gt;

&lt;p&gt;What are your experiences with these query builders? Share your thoughts in the comments!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why NestJS Is The New Gold Standard For Node Backend Development</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Tue, 14 Jan 2025 12:06:00 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/why-nestjs-is-the-new-gold-standard-for-node-backend-development-lm</link>
      <guid>https://dev.to/rayenmabrouk/why-nestjs-is-the-new-gold-standard-for-node-backend-development-lm</guid>
      <description>&lt;p&gt;As a Node.js developer who has tried every Node framework under the sun, here’s why I believe NestJS must be the new gold standard for Node.js backend development. At first, the framework seemed like too much—the learning curve was steep, and I found it hard to understand coming from Express. Why all this complexity? But with time, I came to admire every aspect of this framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;strong&gt;Why OOP is the Best for Backend Development&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Object-Oriented Programming (OOP) is not just a paradigm; it's a methodology that addresses the core challenges of backend development. At its heart, OOP allows you to model real-world problems in a way that makes systems easier to design, implement, and maintain. NestJS utilizes OOP through its class-based approach, enabling you to organize logic into cohesive, reusable components.&lt;/p&gt;

&lt;p&gt;For instance, consider the concept of services in NestJS. A service class encapsulates business logic, promoting separation of concerns. This encapsulation not only makes your codebase easier to navigate but also simplifies testing. Using decorators like &lt;code&gt;@Injectable()&lt;/code&gt;, NestJS takes dependency injection a step further, allowing seamless integration of service dependencies without manual wiring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nf"&gt;createUser&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="kr"&gt;string&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;user&lt;/span&gt; &lt;span class="o"&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="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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="k"&gt;this&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&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="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;Moreover, inheritance in OOP allows developers to extend and reuse functionality without duplicating code. Polymorphism, another cornerstone of OOP, lets you define common interfaces for varying implementations. In a NestJS context, this could be seen in abstract classes for database repositories, where specific implementations handle details for MongoDB, PostgreSQL, or other data stores.&lt;/p&gt;

&lt;p&gt;So as your codebase grows larger, you can maintain a well-structured codebase within every module.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;strong&gt;NestJS is Future-Proof&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;NestJS positions itself as a framework built to withstand the test of time. Its adoption of TypeScript ensures that your code is reliable and maintainable.&lt;/p&gt;

&lt;p&gt;NestJS also uses decorators extensively, aligning with modern JavaScript standards such as ES6+ and ECMAScript proposals. These decorators, like &lt;code&gt;@Controller()&lt;/code&gt;, &lt;code&gt;@Get()&lt;/code&gt;, and &lt;code&gt;@Post()&lt;/code&gt;, provide declarative syntax that makes code intuitive and reduces boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Get&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&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="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;findAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This action returns all users&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. &lt;strong&gt;Ideal for Microservices and Enterprise Applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;NestJS shines in environments where modularity and scalability are non-negotiable. For microservices, NestJS provides native support for distributed systems using patterns like message brokers and event-driven communication. The framework includes modules for integration with RabbitMQ, Kafka, and Redis, making it easy to design resilient and decoupled systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MessagePattern&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/microservices&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="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;MessagePattern&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notifications&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;handleNotification&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="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Received notification:&lt;/span&gt;&lt;span class="dl"&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="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;For enterprise-grade applications, NestJS's modular architecture allows teams to work on isolated modules without stepping on each other’s toes. Features like &lt;code&gt;DynamicModule&lt;/code&gt; allow you to configure modules dynamically, simplifying the management of multi-tenant systems or applications with environment-specific configurations.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Built-in Support for Everything
&lt;/h2&gt;

&lt;p&gt;NestJS eliminates the need for cobbling together third-party libraries by offering built-in support for a wide array of features. Need WebSocket support for real-time applications? NestJS provides an out-of-the-box module for that. Building a GraphQL API? NestJS's GraphQL module integrates seamlessly with decorators for schema-first or code-first approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;

&lt;p&gt;Integrating JWT authentication using Passport.js:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PassportStrategy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/passport&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ExtractJwt&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passport-jwt&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JwtStrategy&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PassportStrategy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;jwtFromRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExtractJwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAuthHeaderAsBearerToken&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;secretOrKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secretKey&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&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="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&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;p&gt;For authentication, the &lt;code&gt;@nestjs/passport&lt;/code&gt; library integrates Passport.js directly into your project, providing strategies for OAuth, JWT, and local authentication. NestJS also simplifies database interaction with its &lt;code&gt;@nestjs/typeorm&lt;/code&gt; and &lt;code&gt;@nestjs/mongoose&lt;/code&gt; modules, providing tight integration with popular ORMs like TypeORM and Mongoose.&lt;/p&gt;

&lt;p&gt;This all-inclusive approach reduces decision fatigue and ensures consistency across your application, allowing you to focus on solving business problems rather than configuring your stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;strong&gt;Modular Architecture That Scales&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;NestJS’s modular system is a game-changer for large-scale applications. By encapsulating features into dedicated modules, it allows developers to maintain clean boundaries between different parts of the application. Each module in NestJS acts as a self-contained unit, bundling together controllers, services, and other components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;

&lt;p&gt;Creating a user module:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserController&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.controller&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./user.service&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="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;controllers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserController&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The modular design allows you to separate concerns and easily scale your application by adding new modules.&lt;/p&gt;

&lt;p&gt;NestJS also supports lazy loading of modules, a crucial feature for microservices or applications with large, complex dependencies. This ensures that your application starts faster and consumes fewer resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;strong&gt;Very Hard to Mess Up in NestJS&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;NestJS offers guardrails that make it difficult to write bad code. Its opinionated structure enforces best practices, such as the separation of concerns, dependency injection, and modular design. The framework's CLI (&lt;code&gt;@nestjs/cli&lt;/code&gt;) helps scaffold components with a consistent folder structure, eliminating the guesswork in organizing your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Example
&lt;/h3&gt;

&lt;p&gt;Using guards for role-based access control:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CanActivate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ExecutionContext&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&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="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RolesGuard&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanActivate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;canActivate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ExecutionContext&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&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;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switchToHttp&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;getRequest&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&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;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, NestJS makes full use of TypeScript to catch errors during development, reducing runtime bugs. Features like guards (&lt;code&gt;@CanActivate&lt;/code&gt;), interceptors (&lt;code&gt;@Interceptor()&lt;/code&gt;), and pipes (&lt;code&gt;@PipeTransform&lt;/code&gt;) provide clear patterns for handling concerns like validation, transformation, and access control. This layered approach ensures that even junior developers can contribute effectively while adhering to established conventions.&lt;/p&gt;

&lt;p&gt;Even error handling is simplified. By extending the built-in &lt;code&gt;HttpException&lt;/code&gt;, you can create custom exceptions with ease, ensuring your APIs remain consistent and predictable. NestJS takes care of the rest, including sending the appropriate HTTP response codes and error messages.&lt;/p&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;NestJS isn’t just another Node.js framework; it’s a paradigm shift in backend development. It’s an ideal choice, offering everything you need to succeed. From my experience, I believe this framework strikes the perfect balance between rapid delivery and long-term maintainability. It represents the ultimate evolution of Node.js backend development, setting a new standard for scalability and efficiency.&lt;br&gt;
For more in-depth insights, check out the book &lt;strong&gt;Scalable Application Development with NestJS&lt;/strong&gt;, available &lt;a href="https://www.packtpub.com/en-us/product/scalable-application-development-with-nestjs-9781835463956?utm_medium=affiliate&amp;amp;utm_campaign=1609a0e8-a37d-c05e-295c-6780c796351a&amp;amp;utm_term=e2025f61-d111-eb11-a812-00224801bc77&amp;amp;utm_content=B21694" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>node</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Ultimate Tech Stack for Startups in 2025</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Fri, 27 Dec 2024 23:33:44 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/best-tech-stack-for-startups-in-2025-5h2l</link>
      <guid>https://dev.to/rayenmabrouk/best-tech-stack-for-startups-in-2025-5h2l</guid>
      <description>&lt;p&gt;As the tech landscape evolves, choosing the right tech stack is like picking the perfect recipe for success. At &lt;a href="https://evowave.tech" rel="noopener noreferrer"&gt;Evowave&lt;/a&gt;, we’ve crafted a tech stack that’s powerful, efficient, and delightful, enabling us to build fast, modern, and visually stunning applications. Let’s dive into the tools and technologies we’re using in 2025—and why we believe they’re startup gold.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend: Next.js 14 with React Query and Context API
&lt;/h3&gt;

&lt;p&gt;💻 &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;NextJs&lt;/a&gt; 14 is our secret weapon for building web applications that are lightning-fast and user-friendly. Here’s why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server-side rendering (SSR)&lt;/strong&gt; and &lt;strong&gt;static site generation (SSG)&lt;/strong&gt; deliver outstanding performance.&lt;/li&gt;
&lt;li&gt;Built-in app directory and routing make development efficient and streamlined.&lt;/li&gt;
&lt;li&gt;Features like TurboPack and enhanced performance optimizations take the developer experience to the next level.&lt;/li&gt;
&lt;li&gt;The framework is constantly updated, with exciting new features in the pipeline, especially in NextJs 15.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For state management and data fetching, we rely on &lt;strong&gt;React Query&lt;/strong&gt; and &lt;strong&gt;Context API&lt;/strong&gt;. Here's where the magic happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://tanstack.com/query/latest/docs/framework/react/overview" rel="noopener noreferrer"&gt;React Query&lt;/a&gt; is a powerhouse for remote state management, simplifying data synchronization, caching, and background updates. It’s packed with advanced features that make complex data flows effortless.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/react/useContext" rel="noopener noreferrer"&gt;Context API&lt;/a&gt; is our lightweight solution for sharing state across components. Paired with custom hooks, it’s simple, yet powerful—perfect for most commercial websites.
💡 This dream team lets us prefetch data like pros, ensuring seamless, fast, and highly responsive user experiences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Backend: Supabase and NestJS
&lt;/h3&gt;

&lt;p&gt;⚡ When it comes to the backend, we tailor our approach to the project’s needs, alternating between &lt;strong&gt;Supabase&lt;/strong&gt; and &lt;strong&gt;NestJS&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; Think of it as the ultimate backend-as-a-service solution. It offers real-time subscriptions, PostgreSQL database hosting, and built-in authentication. Combined with Next.js, it’s an unbeatable combo that speeds up development like nothing else. Plus, the paid tier provides exceptional value for the features it offers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nestjs.com/" rel="noopener noreferrer"&gt;NestJS&lt;/a&gt; For larger, more complex projects, NestJS is our go-to framework for organization and scalability, built to support enterprise-grade applications with TypeScript. If you want a backend that scales with your app, NestJS is the perfect choice.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these tools give us unmatched flexibility and power, allowing us to build whatever our projects demand, all while maintaining quality and performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  UI Framework: shadcn/UI
&lt;/h3&gt;

&lt;p&gt;🎨 For creating visually stunning and accessible interfaces, we swear by &lt;a href="https://ui.shadcn.com/" rel="noopener noreferrer"&gt;Shadcn/UI&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Packed with customizable components built on Tailwind CSS.&lt;/li&gt;
&lt;li&gt;Simplifies maintaining a cohesive design system.&lt;/li&gt;
&lt;li&gt;Easy to customize, intuitive to use, and a joy for developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result? User interfaces that are not only beautiful but also incredibly functional!&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Stack Works for Startups
&lt;/h3&gt;

&lt;p&gt;🚀 This stack has been a game-changer for us because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It Balances Speed and Quality&lt;/strong&gt;: Tools like Supabase and shadcn/UI reduce boilerplate code, allowing us to focus on building quality features without compromising on performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It’s Lightning-Fast&lt;/strong&gt;: Next.js 14 and React Query ensure our apps load quickly and deliver buttery-smooth interactions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It Scales Effortlessly&lt;/strong&gt;: Whether it's a small MVP or a full-fledged enterprise app, NestJS and Supabase can handle the load as your project grows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It’s Beautiful and Functional&lt;/strong&gt;: With shadcn/UI, our interfaces are both head-turners and highly functional.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;🌍 In 2025, startups must strike the perfect balance between development speed, scalability, and high-quality user experiences. By combining Next.js 14, React Query, useContext, Supabase, NestJS, and shadcn/UI, we’ve built a stack that achieves just that.&lt;/p&gt;

&lt;p&gt;If you’re gearing up for your next project, give this stack a shot. It might just become your secret weapon too..&lt;br&gt;
💬🤔 What stack are you using for your projects in 2025? Let me know in the comments!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>nestjs</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Why Astro’s New Actions are the Upgrade React 19 Devs Have Been Waiting For</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Sat, 26 Oct 2024 21:59:40 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/why-astros-new-actions-are-the-upgrade-react-19-devs-have-been-waiting-for-c25</link>
      <guid>https://dev.to/rayenmabrouk/why-astros-new-actions-are-the-upgrade-react-19-devs-have-been-waiting-for-c25</guid>
      <description>&lt;p&gt;React 19 introduced several exciting features, particularly in server-side interaction with Server Actions. These actions aim to streamline server calls, allowing developers to handle requests more effectively without extensive API boilerplate. However, they brought challenges, particularly in form handling, error management, and debugging. Astro’s new Actions, introduced with Astro 4.15, provide a promising alternative that addresses some of the limitations observed in React 19’s Server Actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issues with React 19 Server Actions
&lt;/h2&gt;

&lt;p&gt;React’s Server Actions simplify server-side interactions but come with specific limitations that can impact developer experience:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Complex Form Data Handling&lt;/strong&gt;: Server Actions in React require handling form data manually as &lt;code&gt;FormData&lt;/code&gt; objects. This manual extraction means developers need to cast or convert values into the desired types, often resulting in boilerplate code.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Converts to a number&lt;/span&gt;
   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;isActive&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;on&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Handles checkbox values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Error Handling&lt;/strong&gt;: Server Actions in React 19 lack built-in server-side error handling mechanisms. Errors in the server response default to a 200 OK status code, which can complicate client-side error management, making it challenging to distinguish success from failure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Obfuscated Endpoint Names&lt;/strong&gt;: Server Actions are not treated as traditional server endpoints but as function-like units. This approach can lead to hashed endpoint names, making debugging challenging as developers may struggle to map these hashed endpoints to actual functionality.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F8oe6e3e9xxlu2x7q4759.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%2F8oe6e3e9xxlu2x7q4759.png" alt="Example from React Conf with hashed endpoint names" width="671" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Astro’s Actions: A Game-Changer
&lt;/h2&gt;

&lt;p&gt;Astro’s Actions address these limitations, offering an improved approach to server-side interaction. Here’s how Astro’s features provide enhanced support over React 19’s Server Actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Form Data Handling with Type Safety&lt;/strong&gt;: Astro's Actions utilize &lt;code&gt;zod&lt;/code&gt; for schema validation, allowing automatic parsing and type-safe form data handling. This reduces boilerplate and ensures that form inputs are converted to the correct data types by default.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineAction&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;astro:actions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;astro:schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;getGreeting&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;defineAction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;input&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="p"&gt;}),&lt;/span&gt;
       &lt;span class="na"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Specifies form data handling&lt;/span&gt;
       &lt;span class="na"&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;input&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;// this is a typesafe object now !&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;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Hello, &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="s2"&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;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Improved Error Handling&lt;/strong&gt;: Astro’s Actions introduce &lt;code&gt;ActionError&lt;/code&gt;, enabling more accurate HTTP status codes and messages for error handling, resembling traditional server endpoints. This functionality offers granular error control and clearer client-server communication.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineAction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ActionError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;astro:actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;import&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;astro:schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="na"&gt;likePost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;defineAction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="na"&gt;input&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;postId&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="p"&gt;}),&lt;/span&gt;
       &lt;span class="na"&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;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-session&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ActionError&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
             &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UNAUTHORIZED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;User must be logged in.&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="p"&gt;}&lt;/span&gt;
         &lt;span class="c1"&gt;// Process request if authorized&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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Readable Endpoint Names&lt;/strong&gt;: Unlike React's hashed endpoints, Astro’s Actions use developer-defined names for endpoints, which makes debugging and tracing calls significantly easier.&lt;/li&gt;
&lt;/ol&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%2Fptz72a3647oooku8ccwf.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%2Fptz72a3647oooku8ccwf.png" alt="Readable endpoint names example from Astro" width="558" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Progressive Enhancement and Additional Resources&lt;/strong&gt;: Astro focuses on Progressive Enhancement, allowing functionality to work even with JavaScript disabled. This aligns with Astro’s commitment to a lighter, more accessible web, ensuring that core functionalities remain intact without relying on JavaScript execution.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For further insights on Astro’s Actions, explore &lt;a href="https://docs.astro.build/en/guides/actions/" rel="noopener noreferrer"&gt;Astro actions docs&lt;/a&gt;, which dives into the details of integrating Actions in modern applications.&lt;/p&gt;

</description>
      <category>react</category>
      <category>astro</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Keycloak: The Ultimate Open-Source Access Management Solution</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Tue, 30 Jul 2024 17:37:00 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/keycloak-the-ultimate-open-source-access-management-solution-3map</link>
      <guid>https://dev.to/rayenmabrouk/keycloak-the-ultimate-open-source-access-management-solution-3map</guid>
      <description>&lt;h2&gt;
  
  
  What is Keycloak?
&lt;/h2&gt;

&lt;p&gt;Keycloak is a robust, flexible, and feature-rich IAM (Identity and Access Management) platform developed by &lt;strong&gt;Red Hat&lt;/strong&gt;. It provides a centralized authentication and authorization service for web applications, mobile apps, and RESTful web services. Keycloak acts as a standalone server that can be easily integrated with existing systems, offering Single Sign-On (SSO), social login, user federation, client adapters, and an administration console out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Red Hat is Awesome
&lt;/h2&gt;

&lt;p&gt;Red Hat is like the superhero of the tech world! They’re the wizards behind some of the coolest open-source tools that businesses use every day. Think of them as the friendly giants who make sure everything is secure, up-to-date, and running smoothly. They’re always innovating and working with the community to create awesome enterprise-grade solutions like Red Hat Enterprise Linux (RHEL) and OpenShift. Basically, Red Hat is the techie you want on your side if you want things done right and with a touch of magic!&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%2Fri332fm767dp1zcrywms.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%2Fri332fm767dp1zcrywms.jpg" alt=" " width="360" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Centralized Authentication and Authorization
&lt;/h2&gt;

&lt;p&gt;Keycloak allows you to centralize your authentication services, eliminating the need to implement security features in each application separately. This means that instead of copying the same code across multiple apps, you can simply use the client feature and create a new client in your Keycloak realm, allowing you to scale and add more apps easily.&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%2Fpa5rzzp8qfm0tz1veele.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%2Fpa5rzzp8qfm0tz1veele.png" alt=" " width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Sign-On (SSO), Social Login and Identity Brokering
&lt;/h2&gt;

&lt;p&gt;Keycloak supports all of them out of the box! With Keycloak, users can authenticate once and access multiple applications without the need to log in again. It also supports login with popular social media platforms like Google, Facebook, and GitHub. Additionally, it allows for easy integration with existing identity providers, making it simple to federate user identities across different systems.&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%2Felg67igk2nfq0pxsgfn9.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%2Felg67igk2nfq0pxsgfn9.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizable and Extensible
&lt;/h2&gt;

&lt;p&gt;Keycloak offers extensive customization options, from theming login pages to extending core functionalities through custom Service Provider Interfaces (SPIs). This flexibility allows organizations to tailor the authentication experience to their specific needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Role Management System
&lt;/h2&gt;

&lt;p&gt;Roles can be defined globally or at the client level, enabling flexible and scalable access control strategies. Here are some key features of the role management system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global and Client Roles&lt;/strong&gt;: Global roles apply across the entire realm (All your apps), while client roles are specific to individual applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Composite Roles&lt;/strong&gt;: Roles can be grouped into composite roles, allowing for hierarchical and modular permission management.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role Mapping&lt;/strong&gt;: Users and groups can be assigned specific roles, and roles can be mapped to specific permissions, making it easy to manage user access.&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%2Fjvlqp0i7he96iw79m2nj.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%2Fjvlqp0i7he96iw79m2nj.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Use Cases Support
&lt;/h2&gt;

&lt;p&gt;Keycloak also supports a wide range of advanced use cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-tenancy Support&lt;/strong&gt;: With its concept of "realms," Keycloak enables organizations to manage multiple tenants or client organizations within a single instance, each with its own set of users, roles, and configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Robust Security Features&lt;/strong&gt;: Keycloak includes built-in security features such as brute force detection, password policies, and session management, helping to protect against common security threats.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Federation&lt;/strong&gt;: Keycloak can integrate with existing user directories like LDAP or Active Directory, allowing organizations to leverage their current user management systems while benefiting from its advanced features.&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%2Fuld9hj5zi895cy2mi274.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%2Fuld9hj5zi895cy2mi274.png" alt=" " width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keycloak is a powerful and flexible access management solution. Its simple integration with existing systems makes it a top choice for enhancing application security without extra hassle. Developers can focus on building core features, trusting Keycloak to handle security!&lt;/p&gt;

&lt;p&gt;Of course his article gives a general overview of this amazing open-source IAM. We'll dive deeper into its usage and maintenance in future articles.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Concurrency and Parallelism: What's the Difference?</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Tue, 18 Jun 2024 17:23:13 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/understanding-concurrency-and-parallelism-whats-the-difference-3d45</link>
      <guid>https://dev.to/rayenmabrouk/understanding-concurrency-and-parallelism-whats-the-difference-3d45</guid>
      <description>&lt;p&gt;In this article, we will discuss the concepts of concurrency and parallelism, the differences between them, and the challenges we might face while implementing them. Let's dive in 🚶‍♀️.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Concurrency?
&lt;/h2&gt;

&lt;p&gt;To understand concurrency, let's start with a simple example.&lt;/p&gt;

&lt;p&gt;Imagine we have an app that receives user requests, and we are operating on a single thread. This means we handle one request at a time, respond to it, and then move on to the next one.&lt;/p&gt;

&lt;p&gt;‼️ But what happens when the number of users increases over time?&lt;/p&gt;

&lt;p&gt;In this case, the system will become very slow, similar to a restaurant where many customers arrive, but only one person is working to serve all of them.&lt;/p&gt;

&lt;p&gt;So, you might think of hiring more people in the restaurant to serve the customers faster.&lt;br&gt;
Similarly, to handle multiple requests in the app simultaneously, we need to use multiple threads to speed up the process and improve performance.&lt;/p&gt;

&lt;p&gt;✅ This is exactly what &lt;strong&gt;Concurrency&lt;/strong&gt; means – working on multiple tasks at the same time 🤝.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Difference Between Concurrency and Parallelism?
&lt;/h2&gt;

&lt;p&gt;Both concurrency and parallelism aim to improve performance, but they work differently.&lt;br&gt;
If you have a set of threads, each performing a specific task:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;Concurrency&lt;/strong&gt;:&lt;br&gt;
The system runs them together through context switching, meaning it runs one thread for a while, then pauses it, and runs another thread, and so on until all tasks are completed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;Parallelism&lt;/strong&gt;:&lt;br&gt;
The threads run simultaneously without switching between them; they operate in parallel.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To achieve parallelism, you need a multi-core processor to run the threads in parallel. In contrast, concurrency can be achieved on a single core by &lt;strong&gt;context switching&lt;/strong&gt; between threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Always Use Multiple Threads to Improve Performance?
&lt;/h2&gt;

&lt;p&gt;◀️ There are many challenges and potential issues to be aware of and avoid (which we will discuss later).&lt;br&gt;
If your task is simple and doesn't require multiple threads, then avoid adding unnecessary complexity. However, if you really need to improve performance, then using multiple threads is fine.&lt;/p&gt;

&lt;p&gt;Here are some common problems you might encounter and should be careful about to prevent issues in your application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Race Condition&lt;/li&gt;
&lt;li&gt;Deadlock&lt;/li&gt;
&lt;li&gt;Starvation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will discuss these problems in detail in future articles..&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Step-by-Step Guide to Typesafe Translations in Next.js Without Third-Party Tools</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Mon, 10 Jun 2024 17:44:10 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/step-by-step-guide-to-typesafe-translations-in-nextjs-without-third-party-tools-2mii</link>
      <guid>https://dev.to/rayenmabrouk/step-by-step-guide-to-typesafe-translations-in-nextjs-without-third-party-tools-2mii</guid>
      <description>&lt;p&gt;Multilingual support is a critical feature for modern web applications. In this guide, we will walk through how to implement a typesafe translation system in a Next.js application without relying on any third-party libraries. This approach ensures that our translations are robust and maintainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Define Translation Data
&lt;/h2&gt;

&lt;p&gt;Create a directory named &lt;strong&gt;locales&lt;/strong&gt; at the root of your project to store your translation files. Inside this directory, create JSON files for each language you want to support. For example, &lt;strong&gt;en.json&lt;/strong&gt; for English and &lt;strong&gt;es.json&lt;/strong&gt; for Spanish.&lt;/p&gt;

&lt;p&gt;locales/en.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"greeting"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"farewell"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Goodbye"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;locales/es.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"greeting"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"farewell"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Adiós"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Create Server Action getTranslation
&lt;/h2&gt;

&lt;p&gt;Define a server action named &lt;code&gt;getTranslation.ts&lt;/code&gt; to fetch translation data. Here, we utilize an object called dictionaries, mapping language codes to functions that dynamically import the corresponding JSON file.&lt;/p&gt;

&lt;p&gt;getTranslation.ts:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&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;dictionaries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;en&lt;/span&gt;&lt;span class="p"&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./locales/en.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;es&lt;/span&gt;&lt;span class="p"&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./locales/es.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;};&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;getTranslation&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;defaultLang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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="nf"&gt;getPreferredLang&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Optional: Determine user's preferred language&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lang&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;dictionaries&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="nx"&gt;defaultLang&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;error&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;h2&gt;
  
  
  Step 3: Create useTranslation Hook
&lt;/h2&gt;

&lt;p&gt;In this example, I used React Query for managing state, but feel free to use any other state management solution of your choice. The main objective remains constant: crafting a versatile hook responsible for fetching translations, thereby enabling its use as a client-side state.&lt;/p&gt;

&lt;p&gt;useTranslation.ts:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getTranslation&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/translation/getTranslation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTranslation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lang&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getTranslation&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;h2&gt;
  
  
  Step 4: Integrate Translation in Your Components
&lt;/h2&gt;

&lt;p&gt;Now, let's use our custom hook in an Next.js client component.&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%2F5cwfycsmp9wt8gapvzs9.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%2F5cwfycsmp9wt8gapvzs9.png" alt=" " width="776" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also use the &lt;code&gt;getTranslation()&lt;/code&gt; server action directly in your server components.&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%2F9mibl1w32usdk77escwb.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%2F9mibl1w32usdk77escwb.png" alt=" " width="717" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>tutorial</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Advanced Server Rendering | React Query with Next.js App Router</title>
      <dc:creator>Rayen Mabrouk</dc:creator>
      <pubDate>Thu, 30 May 2024 18:10:05 +0000</pubDate>
      <link>https://dev.to/rayenmabrouk/advanced-server-rendering-react-query-with-nextjs-app-router-bi7</link>
      <guid>https://dev.to/rayenmabrouk/advanced-server-rendering-react-query-with-nextjs-app-router-bi7</guid>
      <description>&lt;p&gt;In this guide you'll learn how to use React Query with server rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Server Rendering?
&lt;/h2&gt;

&lt;p&gt;Server rendering is generating the initial HTML on the server so users see some content immediately when the page loads. This can be done in two ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-Side Rendering (SSR):&lt;/strong&gt; Generates HTML on the server each time a page is requested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Site Generation (SSG):&lt;/strong&gt; Pre-generates HTML at build time or uses cached versions from previous requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Server Rendering Useful?
&lt;/h2&gt;

&lt;p&gt;With client rendering, the process looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load markup without content.&lt;/li&gt;
&lt;li&gt;Load JavaScript.&lt;/li&gt;
&lt;li&gt;Fetch data with queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This requires &lt;strong&gt;at least three server roundtrips&lt;/strong&gt; before the user sees any content.&lt;/p&gt;

&lt;p&gt;Server rendering simplifies this process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load markup with content and initial data.&lt;/li&gt;
&lt;li&gt;Load JavaScript. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The user sees content as soon as step 1 is complete&lt;/strong&gt;, and the page becomes interactive after step 2. The initial data is already included in the markup, so there's no need for an extra data fetch initially!&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does This Relate to React Query?
&lt;/h2&gt;

&lt;p&gt;Using React Query you can Prefetch data before generating/rendering the markup On the server then use the data on the client to avoid a new fetch.&lt;br&gt;
Now how to implement these steps..&lt;/p&gt;
&lt;h2&gt;
  
  
  Initial setup
&lt;/h2&gt;

&lt;p&gt;The first steps of using React Query is always to create a queryClient and wrap the application in a &lt;code&gt;&amp;lt;QueryClientProvider&amp;gt;&lt;/code&gt;. When doing server rendering, it's important to create the queryClient instance inside of your app, in React state (an instance ref works fine too). This ensures that data is not shared between different users and requests, while still only creating the queryClient once per component lifecycle.&lt;/p&gt;

&lt;p&gt;store.tsx:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueryClientProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;queryClient&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;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;QueryClientProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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="nx"&gt;children&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;/QueryClientProvider&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;layout.tsx:&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;import&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/provider/store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="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;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&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;body&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;Store&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;children&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;/Store&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;/body&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;/html&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;h2&gt;
  
  
  Using the Hydration APIs
&lt;/h2&gt;

&lt;p&gt;With just a little more setup, you can use a &lt;strong&gt;queryClient&lt;/strong&gt; to prefetch queries during a preload phase, pass a serialized version of that queryClient to the rendering part of the app, and reuse it there. This avoids the drawbacks mentioned earlier.&lt;/p&gt;

&lt;p&gt;hydration.tsx :&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;dehydrate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;HydrationBoundary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/api/getData&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;Hydration&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;staleTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// this sets the cache time to 5 minutes&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="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetchQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profiles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profiles&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="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prefetchQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;permissions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;permissions&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="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;HydrationBoundary&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;dehydrate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryClient&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="nx"&gt;children&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;/HydrationBoundary&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;The new layout.tsx:&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;import&lt;/span&gt; &lt;span class="nx"&gt;Hydration&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/provider/hydration&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Store&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/provider/store&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="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;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&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;body&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;Store&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;Hydration&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;children&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;/Hydration&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;/Store&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;/body&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;/html&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;at a general level, these are the extra steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a constant queryClient using &lt;code&gt;new QueryClient(options)&lt;/code&gt; (It is important that you set a &lt;strong&gt;staleTime&lt;/strong&gt; otherwise, React Query will refetch the data as soon as it reaches the client).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use &lt;code&gt;await queryClient.prefetchQuery(...)&lt;/code&gt; for each query you want to prefetch.&lt;br&gt;
Use &lt;code&gt;await Promise.all(...)&lt;/code&gt; to fetch the queries in parallel when possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It's fine to have queries that aren't prefetched&lt;/strong&gt;. These won't be server-rendered; instead, they will be fetched on the client after the application is interactive. This can be great for content shown only after user interaction or content far down on the page to avoid blocking more critical content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wrap your tree with &lt;code&gt;&amp;lt;HydrationBoundary state={dehydrate(queryClient)}&amp;gt;&lt;/code&gt; where dehydratedState comes from the framework loader.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  An Important Detail
&lt;/h2&gt;

&lt;p&gt;When using React Query with server rendering, there are actually &lt;strong&gt;three queryClient instances&lt;/strong&gt; involved in the process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Preloading Phase: &lt;br&gt;
Before rendering, a queryClient is created to prefetch data.&lt;br&gt;
Necessary data is fetched and stored in this queryClient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server Rendering Phase:&lt;br&gt;
Once data is prefetched, it's dehydrated (serialized) and sent to the server rendering process.&lt;br&gt;
A new queryClient is created on the server and injected with dehydrated data.&lt;br&gt;
This ensures the server generates fully populated HTML for the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Client Rendering Phase:&lt;br&gt;
Dehydrated data is passed to the client.&lt;br&gt;
Another queryClient is created on the client and rehydrated with the data.&lt;br&gt;
This ensures the client starts with the same data, maintaining consistency and skipping initial data fetching.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This ensures all processes start with the same data, so they can return the same markup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then with the &lt;code&gt;useQuery()&lt;/code&gt; hook, you can use your prefetched queries as you normally would, and the data will be prefetched during the preloading phase. This means that when you use &lt;code&gt;useQuery()&lt;/code&gt; to fetch data in your components, React Query will automatically handle the prefetching of that data before the component renders. This helps improve the performance of your application by ensuring that the data is available when needed.&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/api/getData&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tanstack/react-query&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;profiles&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profiles&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;profiles&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;permissions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
   &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&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="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;permissions&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  High memory consumption on the server
&lt;/h2&gt;

&lt;p&gt;When you create a QueryClient for each request in React Query, it generates an isolated cache specific to that client. This cache remains in memory for a specified period known as the &lt;strong&gt;gcTime&lt;/strong&gt;. If there's a high volume of requests within that period, it can lead to significant memory consumption on the server.&lt;/p&gt;

&lt;p&gt;By default, on the server, &lt;strong&gt;gcTime&lt;/strong&gt; is set to &lt;strong&gt;Infinity&lt;/strong&gt;, meaning manual garbage collection is disabled, and memory is automatically cleared once a request is completed. However, if you set a &lt;strong&gt;non-Infinity gcTime&lt;/strong&gt;, you're responsible for clearing the cache early to prevent excessive memory usage.&lt;/p&gt;

&lt;p&gt;Avoid setting &lt;strong&gt;gcTime&lt;/strong&gt; to 0, as it might cause a hydration error. The Hydration Boundary places necessary data into the cache for rendering. If the garbage collector removes this data before rendering completes, it can cause issues. Instead, consider setting it to 2 * 1000, allowing sufficient time for the app to reference the data.&lt;/p&gt;

&lt;p&gt;To manage memory consumption and clear the cache when it's no longer needed, you can call &lt;code&gt;queryClient.clear()&lt;/code&gt; after handling the request and sending the dehydrated state to the client. Alternatively, you can opt for a smaller &lt;strong&gt;gcTime&lt;/strong&gt; to automatically clear memory sooner. This ensures efficient memory usage and prevents memory-related issues on the server.&lt;/p&gt;

&lt;p&gt;example:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;defaultOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;queries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;gcTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// this sets the garbage collection time to 2 seconds&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;p&gt;In wrapping up, React Query simplifies the process of fetching and caching data, especially when dealing with server-side rendering. By fetching data in advance on the server and seamlessly transferring it to the client, React Query ensures a smooth and consistent user experience. Plus, with features like adjusting the memory management settings, developers can fine-tune performance to meet their application's needs. With React Query, developers can focus on building engaging applications without worrying about complex data management tasks, ultimately delivering faster and more responsive user experiences.&lt;/p&gt;

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