<?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: Ahmed Niazy</title>
    <description>The latest articles on DEV Community by Ahmed Niazy (@ahmed_niazy).</description>
    <link>https://dev.to/ahmed_niazy</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%2F3155204%2Fd322503a-657e-4828-8dac-a6ec5f6acf02.png</url>
      <title>DEV Community: Ahmed Niazy</title>
      <link>https://dev.to/ahmed_niazy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahmed_niazy"/>
    <language>en</language>
    <item>
      <title>Advanced TypeScript Type System — The Complete Deep Dive</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Tue, 17 Feb 2026 06:47:52 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/advanced-typescript-type-system-the-complete-deep-dive-103m</link>
      <guid>https://dev.to/ahmed_niazy/advanced-typescript-type-system-the-complete-deep-dive-103m</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7n10p5oi1ykocy5125h7.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%2F7n10p5oi1ykocy5125h7.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  📚 Table of Contents
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Quick Type System Refresher
&lt;/li&gt;
&lt;li&gt;How Type Narrowing Works Internally
&lt;/li&gt;
&lt;li&gt;Conditional Types — Beyond Basics
&lt;/li&gt;
&lt;li&gt;Distributive Conditional Types Deep Mechanics
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;infer&lt;/code&gt; Keyword — Pattern Matching in Types
&lt;/li&gt;
&lt;li&gt;Mapped Types Internals
&lt;/li&gt;
&lt;li&gt;Key Remapping &amp;amp; Property Filtering
&lt;/li&gt;
&lt;li&gt;Template Literal Types as a Type-Level DSL
&lt;/li&gt;
&lt;li&gt;Recursive Types &amp;amp; Type-Level Recursion
&lt;/li&gt;
&lt;li&gt;Building Advanced Custom Utility Types
&lt;/li&gt;
&lt;li&gt;Reverse Engineering DefinitelyTyped
&lt;/li&gt;
&lt;li&gt;Variance — The Hidden Foundation
&lt;/li&gt;
&lt;li&gt;Union to Intersection — The “Variance Hack” Explained
&lt;/li&gt;
&lt;li&gt;Higher-Order Types &amp;amp; Type-Level Function Composition
&lt;/li&gt;
&lt;li&gt;Advanced &lt;code&gt;infer&lt;/code&gt; Tricks (Tuples, Promises, and More)
&lt;/li&gt;
&lt;li&gt;Type-Level Parsing (String Manipulation)
&lt;/li&gt;
&lt;li&gt;Building a Fully Type-Safe Event System
&lt;/li&gt;
&lt;li&gt;Exhaustiveness Checking with &lt;code&gt;never&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compiler Limits — What Actually Breaks
&lt;/li&gt;
&lt;li&gt;Performance Impact of Complex Types
&lt;/li&gt;
&lt;li&gt;Practical Guidelines for Production Systems
&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  1️⃣ Quick Type System Refresher (In 5 Minutes)
&lt;/h1&gt;

&lt;p&gt;TypeScript is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structurally typed
&lt;/li&gt;
&lt;li&gt;Gradually typed
&lt;/li&gt;
&lt;li&gt;Erased at runtime
&lt;/li&gt;
&lt;li&gt;Control-flow aware
&lt;/li&gt;
&lt;li&gt;Turing complete at the type level (with limits)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Structural Typing
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Admin&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&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="nl"&gt;role&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Admin&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ahmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;super&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&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;admin&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ Valid (structural typing)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;Type compatibility depends on structure, not name.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣ How Type Narrowing Works Internally
&lt;/h1&gt;

&lt;p&gt;Type narrowing is powered by &lt;strong&gt;Control Flow Analysis (CFA)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When TypeScript analyzes this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
function process(value: string | number) {&lt;br&gt;
  if (typeof value === "string") {&lt;br&gt;
    value.toUpperCase();&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Internally:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A &lt;strong&gt;Control Flow Graph (CFG)&lt;/strong&gt; is created.&lt;/li&gt;
&lt;li&gt;Each branch refines possible types.&lt;/li&gt;
&lt;li&gt;The compiler intersects original type with the narrowed constraint.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example: Discriminated Union
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Shape =&lt;br&gt;
  | { kind: "circle"; radius: number }&lt;br&gt;
  | { kind: "square"; side: number };&lt;/p&gt;

&lt;p&gt;function area(shape: Shape) {&lt;br&gt;
  if (shape.kind === "circle") {&lt;br&gt;
    return Math.PI * shape.radius ** 2;&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;TypeScript understands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kind&lt;/code&gt; is a literal discriminator&lt;/li&gt;
&lt;li&gt;Each variant is mutually exclusive&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;if&lt;/code&gt; branch removes incompatible members&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not magic — it’s a refinement process.&lt;/p&gt;




&lt;h1&gt;
  
  
  3️⃣ Conditional Types — The Core Engine
&lt;/h1&gt;

&lt;p&gt;Conditional types are the backbone of advanced type logic.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type IsString = T extends string ? true : false;&lt;/p&gt;

&lt;p&gt;type A = IsString&amp;lt;"hello"&amp;gt;; // true&lt;br&gt;
type B = IsString;  // false&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Happens?
&lt;/h2&gt;

&lt;p&gt;The compiler:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Substitutes &lt;code&gt;T&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Checks assignability (&lt;code&gt;T extends U&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Produces one branch&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is &lt;strong&gt;type-level branching&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  4️⃣ Distributive Conditional Types — Hidden Power
&lt;/h1&gt;

&lt;p&gt;When a &lt;strong&gt;naked type parameter&lt;/strong&gt; appears on the left side of &lt;code&gt;extends&lt;/code&gt;, distribution occurs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Wrap = T extends any ? { value: T } : never;&lt;/p&gt;

&lt;p&gt;type Result = Wrap;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Expands into:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
{ value: string } | { value: number }&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Because unions are treated element-wise when &lt;code&gt;T&lt;/code&gt; is “naked”.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prevent Distribution
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Wrap&amp;lt;T&amp;gt; = [T] extends [any] ? { value: T } : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wrapping in a tuple disables distribution.&lt;/p&gt;




&lt;h1&gt;
  
  
  5️⃣ The &lt;code&gt;infer&lt;/code&gt; Keyword — Type Pattern Matching
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;infer&lt;/code&gt; allows extracting types during conditional matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract Return Type
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type GetReturn&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends (...args: any[]) =&amp;gt; infer R ? R : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract First Argument
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type FirstArg&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends (arg: infer A, ...rest: any[]) =&amp;gt; any ? A : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Extraction Example
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type UnwrapPromise&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends Promise&amp;lt;infer U&amp;gt; ? U : T;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is essentially &lt;strong&gt;pattern matching on types&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  6️⃣ Mapped Types — Iteration at Type Level
&lt;/h1&gt;

&lt;p&gt;Mapped types iterate over keys.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Readonly&amp;lt;T&amp;gt; = {&lt;br&gt;
  readonly [K in keyof T]: T[K];&lt;br&gt;
};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mechanism:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;keyof T&lt;/code&gt; becomes a union of keys&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[K in ...]&lt;/code&gt; iterates key-by-key&lt;/li&gt;
&lt;li&gt;A new type is constructed&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  7️⃣ Key Remapping &amp;amp; Property Filtering
&lt;/h1&gt;

&lt;p&gt;Since TypeScript 4.1:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Prefix = {&lt;/p&gt;

&lt;p&gt;};&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Filtering Keys
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type RemoveId = {&lt;/p&gt;

&lt;p&gt;};&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Returning &lt;code&gt;never&lt;/code&gt; removes the key entirely.&lt;/p&gt;




&lt;h1&gt;
  
  
  8️⃣ Template Literal Types — Compile-Time String Engine
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type EventName&amp;lt;T extends string&amp;gt; =&lt;/code&gt;on${Capitalize}`;&lt;/p&gt;

&lt;p&gt;type E = EventName&amp;lt;"click"&amp;gt;; // "onClick"&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cartesian Explosion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Lang = "en" | "ar";&lt;br&gt;
type Key = "title" | "desc";&lt;/p&gt;

&lt;p&gt;type TranslationKey = &lt;code&gt;${Lang}_${Key}&lt;/code&gt;;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Expands into 4 combinations.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ This can grow exponentially with big unions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  9️⃣ Recursive Types — Type-Level Recursion
&lt;/h1&gt;

&lt;p&gt;Example: &lt;code&gt;DeepReadonly&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type DeepReadonly&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends object&lt;br&gt;
    ? { readonly [K in keyof T]: DeepReadonly&amp;lt;T[K]&amp;gt; }&lt;br&gt;
    : T;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What’s happening?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checks if &lt;code&gt;T&lt;/code&gt; is object&lt;/li&gt;
&lt;li&gt;Recursively transforms properties&lt;/li&gt;
&lt;li&gt;Stops at primitives&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Recursion depth is limited (often ~50 instantiations, depends on context).&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  🔟 Building Advanced Custom Utility Types
&lt;/h1&gt;

&lt;h2&gt;
  
  
  DeepPartial
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type DeepPartial&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends object&lt;br&gt;
    ? { [K in keyof T]?: DeepPartial&amp;lt;T[K]&amp;gt; }&lt;br&gt;
    : T;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Keys By Value Type
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type KeysByValue&amp;lt;T, V&amp;gt; = {&lt;br&gt;
  [K in keyof T]: T[K] extends V ? K : never;&lt;br&gt;
}[keyof T];&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Indexing collapses the mapped results into a union.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flatten Nested Object (Caution: can be expensive)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Flatten&amp;lt;T&amp;gt; = {&lt;br&gt;

    T[K] extends object ? Flatten&amp;lt;T[K]&amp;gt; : T[K];&lt;br&gt;
};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣1️⃣ Reverse Engineering DefinitelyTyped
&lt;/h1&gt;

&lt;p&gt;Example inspired by React:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type ComponentProps&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends React.JSXElementConstructor&amp;lt;infer P&amp;gt;&lt;br&gt;
    ? P&lt;br&gt;
    : T extends keyof JSX.IntrinsicElements&lt;br&gt;
      ? JSX.IntrinsicElements[T]&lt;br&gt;
      : {};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;What’s happening?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If it’s a component → extract props via &lt;code&gt;infer&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;If intrinsic element → lookup built-in props&lt;/li&gt;
&lt;li&gt;Otherwise → &lt;code&gt;{}&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DefinitelyTyped heavily uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep conditional nesting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;infer&lt;/code&gt; extraction&lt;/li&gt;
&lt;li&gt;Mapped transformations&lt;/li&gt;
&lt;li&gt;Distributive tricks&lt;/li&gt;
&lt;li&gt;Intersections to merge constraints&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  1️⃣2️⃣ Variance — The Hidden Foundation
&lt;/h1&gt;

&lt;p&gt;Variance defines how subtyping behaves with generics.&lt;/p&gt;

&lt;p&gt;There are 4 flavors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Covariant&lt;/strong&gt;: preserves subtype direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contravariant&lt;/strong&gt;: reverses subtype direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bivariant&lt;/strong&gt;: both directions (often unsafe)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invariant&lt;/strong&gt;: neither direction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Covariance Example
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Box = { value: T };&lt;/p&gt;

&lt;p&gt;type A = Box;&lt;br&gt;
type B = Box;&lt;/p&gt;

&lt;p&gt;const a: A = { value: "x" };&lt;br&gt;
const b: B = a; // ✅&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contravariance (Function Parameters)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Fn = (value: T) =&amp;gt; void;&lt;/p&gt;

&lt;p&gt;let fn1: Fn;&lt;br&gt;
let fn2: Fn;&lt;/p&gt;

&lt;p&gt;fn2 = fn1; // ✅&lt;br&gt;
fn1 = fn2; // ❌ unsafe&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Why? Because if &lt;code&gt;fn1&lt;/code&gt; expects &lt;code&gt;string | number&lt;/code&gt;, assigning a function that only accepts &lt;code&gt;string&lt;/code&gt; can break.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bivariance (Historical Loophole)
&lt;/h2&gt;

&lt;p&gt;Methods on object types can behave bivariantly for compatibility:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Handler&amp;lt;T&amp;gt; = {&lt;br&gt;
  handle(value: T): void;&lt;br&gt;
};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This can be convenient, but also a source of unsoundness.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣3️⃣ Union to Intersection — The “Variance Hack” Explained
&lt;/h1&gt;

&lt;p&gt;This classic utility works because of function parameter contravariance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type UnionToIntersection&amp;lt;U&amp;gt; =&lt;br&gt;
  (U extends any ? (arg: U) =&amp;gt; void : never) extends&lt;br&gt;
  (arg: infer I) =&amp;gt; void&lt;br&gt;
    ? I&lt;br&gt;
    : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s happening step-by-step?
&lt;/h2&gt;

&lt;p&gt;Given:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type U = { a: string } | { b: number };&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Distribute into functions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
U extends any ? (arg: U) =&amp;gt; void : never&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Becomes:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
(arg: { a: string }) =&amp;gt; void&lt;br&gt;
| (arg: { b: number }) =&amp;gt; void&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Infer the parameter
&lt;/h3&gt;

&lt;p&gt;Because parameters are contravariant, inference collapses into an intersection:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
(arg: infer I) =&amp;gt; void&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
{ a: string } &amp;amp; { b: number }&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a deliberate “exploit” of variance mechanics.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣4️⃣ Higher-Order Types &amp;amp; Type-Level Function Composition
&lt;/h1&gt;

&lt;p&gt;TypeScript doesn’t support true Higher-Kinded Types (HKTs), but we can simulate them.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Apply&lt;/code&gt; — Calling a Type-Level Function
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Apply&amp;lt;F, T&amp;gt; =&lt;br&gt;
  F extends { type: (arg: T) =&amp;gt; infer R } ? R : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining a “type-level function”
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type ToArray = {&lt;br&gt;
  type: (arg: T) =&amp;gt; T[];&lt;br&gt;
};&lt;/p&gt;

&lt;p&gt;type R = Apply; // string[]&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Type-Level Composition (“Piping”)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Pipe&amp;lt;A, B&amp;gt; =&lt;br&gt;
  B extends (arg: infer T) =&amp;gt; any&lt;br&gt;
    ? A extends (arg: any) =&amp;gt; T&lt;br&gt;
      ? (arg: Parameters&amp;lt;A&amp;gt;[0]) =&amp;gt; ReturnType&amp;lt;B&amp;gt;&lt;br&gt;
      : never&lt;br&gt;
    : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is compile-time plumbing: connecting one function type to another.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣5️⃣ Advanced &lt;code&gt;infer&lt;/code&gt; Tricks (Tuples, Promises, and More)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Head / Tail of a Tuple
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Head =&lt;br&gt;
  T extends [infer H, ...any[]] ? H : never;&lt;/p&gt;

&lt;p&gt;type Tail =&lt;br&gt;
  T extends [any, ...infer R] ? R : never;&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reverse a Tuple (Recursive)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Reverse&amp;lt;T extends any[]&amp;gt; =&lt;br&gt;
  T extends [infer H, ...infer R]&lt;br&gt;
    ? [...Reverse&amp;lt;R&amp;gt;, H]&lt;br&gt;
    : [];&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract Promise Inner Type
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type AwaitedLike&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends Promise&amp;lt;infer U&amp;gt; ? U : T;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣6️⃣ Type-Level Parsing (String Manipulation)
&lt;/h1&gt;

&lt;p&gt;Template literal types let us parse strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extract Route Params
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type ExtractParams&amp;lt;T extends string&amp;gt; =&lt;br&gt;
  T extends&lt;/code&gt;${string}:${infer Param}/${infer Rest}&lt;code&gt;&lt;br&gt;
    ? Param | ExtractParams&amp;lt;Rest&amp;gt;&lt;br&gt;
    : T extends&lt;/code&gt;${string}:${infer Param}`&lt;br&gt;
      ? Param&lt;br&gt;
      : never;&lt;/p&gt;

&lt;p&gt;type Params = ExtractParams&amp;lt;"/user/:id/post/:postId"&amp;gt;;&lt;br&gt;
// "id" | "postId"&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is a real type-level parser.&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣7️⃣ Building a Fully Type-Safe Event System
&lt;/h1&gt;

&lt;p&gt;Define events:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type EventMap = {&lt;br&gt;
  click: { x: number; y: number };&lt;br&gt;
  login: { userId: string };&lt;br&gt;
  logout: void;&lt;br&gt;
};&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Listener:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Listener&amp;lt;E extends keyof EventMap&amp;gt; =&lt;br&gt;
  (payload: EventMap[E]) =&amp;gt; void;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Emitter:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
class Emitter {&lt;br&gt;
  on(event: E, listener: Listener) {}&lt;/p&gt;

&lt;p&gt;emit(event: E, payload: EventMap[E]) {}&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Usage:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
const emitter = new Emitter();&lt;/p&gt;

&lt;p&gt;emitter.emit("click", { x: 10, y: 20 }); // ✅&lt;br&gt;
emitter.emit("click", { userId: "1" });  // ❌&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Powered by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;keyof&lt;/code&gt; constraints&lt;/li&gt;
&lt;li&gt;indexed access &lt;code&gt;EventMap[E]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;literal inference&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  1️⃣8️⃣ Exhaustiveness Checking with &lt;code&gt;never&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
function assertNever(x: never): never {&lt;br&gt;
  throw new Error("Unexpected value");&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
type Shape =&lt;br&gt;
  | { kind: "circle" }&lt;br&gt;
  | { kind: "square" };&lt;/p&gt;

&lt;p&gt;function handle(shape: Shape) {&lt;br&gt;
  switch (shape.kind) {&lt;br&gt;
    case "circle":&lt;br&gt;
      return;&lt;br&gt;
    case "square":&lt;br&gt;
      return;&lt;br&gt;
    default:&lt;br&gt;
      assertNever(shape); // ✅ compiler error if a case is missing&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  1️⃣9️⃣ Compiler Limits — What Actually Breaks
&lt;/h1&gt;

&lt;p&gt;TypeScript has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instantiation depth limits&lt;/li&gt;
&lt;li&gt;Union size limits&lt;/li&gt;
&lt;li&gt;Memory thresholds&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Extremely Dangerous Pattern (Union Explosion)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Explode&amp;lt;T&amp;gt; =&lt;br&gt;
  T extends any ? { a: T } | { b: T } : never;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Large unions here can grow exponentially.&lt;/p&gt;




&lt;h1&gt;
  
  
  2️⃣0️⃣ Performance Impact of Complex Types
&lt;/h1&gt;

&lt;p&gt;TypeScript types are evaluated during compilation.&lt;/p&gt;

&lt;p&gt;Heavy constructs increase:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Type instantiation count&lt;/li&gt;
&lt;li&gt;Union expansion&lt;/li&gt;
&lt;li&gt;Recursive resolution depth&lt;/li&gt;
&lt;li&gt;IDE memory usage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Errors
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;txt&lt;br&gt;
Type instantiation is excessively deep and possibly infinite.&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;txt&lt;br&gt;
Expression produces a union type that is too complex to represent.&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Causes Slowness?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Deep recursive mapped types&lt;/li&gt;
&lt;li&gt;Large distributive conditional chains&lt;/li&gt;
&lt;li&gt;Template literal cartesian explosions&lt;/li&gt;
&lt;li&gt;Intersections over wide unions&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  2️⃣1️⃣ Practical Guidelines for Production Systems
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ✅ Prefer Shallow Utilities
&lt;/h2&gt;

&lt;p&gt;Avoid deep recursion unless necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Avoid Naked Distribution When Not Needed
&lt;/h2&gt;

&lt;p&gt;Wrap generics in tuples:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
[T] extends [any] ? ... : ...&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Break Complex Types Into Steps
&lt;/h2&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type MegaType&amp;lt;T&amp;gt; = Deep&amp;lt;Transform&amp;lt;Extract&amp;lt;T&amp;gt;&amp;gt;&amp;gt;;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Do:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;ts&lt;br&gt;
type Step1&amp;lt;T&amp;gt; = Extract&amp;lt;T&amp;gt;;&lt;br&gt;
type Step2&amp;lt;T&amp;gt; = Transform&amp;lt;T&amp;gt;;&lt;br&gt;
type Step3&amp;lt;T&amp;gt; = Deep&amp;lt;T&amp;gt;;&lt;br&gt;
type MegaType&amp;lt;T&amp;gt; = Step3&amp;lt;Step2&amp;lt;Step1&amp;lt;T&amp;gt;&amp;gt;&amp;gt;;&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Profile Large Codebases
&lt;/h2&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
tsc --extendedDiagnostics&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




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

&lt;p&gt;TypeScript’s type system is no longer just static annotations.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A functional programming system&lt;/li&gt;
&lt;li&gt;A compile-time evaluator&lt;/li&gt;
&lt;li&gt;A pattern-matching engine&lt;/li&gt;
&lt;li&gt;A string manipulation engine&lt;/li&gt;
&lt;li&gt;A transformation DSL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But with great power comes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexity&lt;/li&gt;
&lt;li&gt;Compilation cost&lt;/li&gt;
&lt;li&gt;Maintenance challenges&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mastering it allows you to build libraries at the level of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Redux Toolkit&lt;/li&gt;
&lt;li&gt;Zod&lt;/li&gt;
&lt;li&gt;tRPC&lt;/li&gt;
&lt;li&gt;Prisma&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>A Deep Dive Into Schema.org Structured Data For SEO</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Thu, 05 Feb 2026 15:22:02 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/a-deep-dive-into-schemaorg-structured-data-for-seo-kcp</link>
      <guid>https://dev.to/ahmed_niazy/a-deep-dive-into-schemaorg-structured-data-for-seo-kcp</guid>
      <description>&lt;p&gt;This article explains a reusable structured data module.&lt;br&gt;
It is typically implemented as a composable or utility.&lt;br&gt;
It is usually written in TypeScript.&lt;br&gt;
It exports a factory function.&lt;br&gt;
That factory returns multiple helper functions.&lt;br&gt;
Each helper function builds a Schema.org JSON LD object.&lt;br&gt;
These objects are meant to be embedded in the page HTML.&lt;br&gt;
Typically you embed them inside a script tag.&lt;br&gt;
The script tag type should be application/ld+json.&lt;br&gt;
Search engines read that JSON LD.&lt;br&gt;
They use it to understand your pages.&lt;br&gt;
They may produce rich results.&lt;br&gt;
They may improve entity understanding.&lt;br&gt;
They may improve crawl interpretation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Important note
&lt;/h1&gt;

&lt;p&gt;This composable only generates plain JavaScript objects.&lt;br&gt;
It does not inject them into head by itself.&lt;br&gt;
You still need to connect the output to your head management.&lt;br&gt;
In most frameworks, you can do that via your head management system.&lt;br&gt;
Or you can use a dedicated structured data integration.&lt;br&gt;
The composable focuses on generation logic.&lt;/p&gt;

&lt;h1&gt;
  
  
  What this file contains
&lt;/h1&gt;

&lt;p&gt;The file contains TypeScript interfaces.&lt;br&gt;
Each interface defines the input shape for a generator.&lt;br&gt;
Then the file defines the schema module.&lt;br&gt;
Inside the schema module there are shared dependencies.&lt;br&gt;
There is a route reference.&lt;br&gt;
There is a locale reference.&lt;br&gt;
There is a configuration reference.&lt;br&gt;
Then there is baseUrl.&lt;br&gt;
baseUrl comes from your configuration.&lt;br&gt;
If baseUrl is missing, it falls back to a default domain.&lt;/p&gt;

&lt;p&gt;After that, the file defines many generator functions.&lt;br&gt;
All of them return a schema object.&lt;br&gt;
Most return an object unconditionally.&lt;br&gt;
One generator returns null when there is no data.&lt;br&gt;
That generator is the FAQ schema generator.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to use outputs in SEO
&lt;/h1&gt;

&lt;p&gt;Search engines do not rank pages just because JSON LD exists.&lt;br&gt;
But JSON LD helps them understand.&lt;br&gt;
Better understanding can lead to better presentation.&lt;br&gt;
Better presentation can lead to better click through.&lt;br&gt;
Rich results can add extra screen space.&lt;br&gt;
Extra screen space can increase trust.&lt;br&gt;
It can also reduce ambiguity.&lt;/p&gt;

&lt;h1&gt;
  
  
  Structured data can help with
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Entity disambiguation&lt;/li&gt;
&lt;li&gt;Site identity&lt;/li&gt;
&lt;li&gt;Publisher identity&lt;/li&gt;
&lt;li&gt;Breadcrumb display&lt;/li&gt;
&lt;li&gt;FAQ rich results&lt;/li&gt;
&lt;li&gt;Job posting rich results&lt;/li&gt;
&lt;li&gt;Product like availability signals for services&lt;/li&gt;
&lt;li&gt;App rich results for SoftwareApplication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact rich result eligibility depends on search engine rules.&lt;br&gt;
But the shapes used here are aligned with common Schema.org patterns.&lt;/p&gt;

&lt;h1&gt;
  
  
  Shared dependencies inside the schema module
&lt;/h1&gt;

&lt;p&gt;The module reads the current route.&lt;br&gt;
It reads the current locale.&lt;br&gt;
It reads baseUrl.&lt;br&gt;
These three values are used by helper methods.&lt;br&gt;
The schema generators themselves accept explicit URLs.&lt;br&gt;
So they are reusable across pages.&lt;/p&gt;

&lt;h1&gt;
  
  
  The helper methods focus on
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Getting the current page URL in a consistent way&lt;/li&gt;
&lt;li&gt;Building breadcrumb items from the route path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we will go function by function.&lt;/p&gt;

&lt;h1&gt;
  
  
  Organization schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;Organization schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function generates a Schema.org Organization entity.&lt;br&gt;
An Organization is often used as the publisher.&lt;br&gt;
It can also represent your brand entity.&lt;br&gt;
It can connect your website to social profiles.&lt;br&gt;
It can add contact and address info.&lt;br&gt;
It can help build a knowledge graph entity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;OrganizationSchemaOptions has these fields&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;logo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;alternateName&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;founder&lt;/li&gt;
&lt;li&gt;foundingDate&lt;/li&gt;
&lt;li&gt;foundingLocation&lt;/li&gt;
&lt;li&gt;telephone&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;address&lt;/li&gt;
&lt;li&gt;contactPoint&lt;/li&gt;
&lt;li&gt;sameAs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;The base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context set to &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type set to Organization&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;logo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it conditionally adds optional fields.&lt;br&gt;
It only adds a field if you provided it.&lt;br&gt;
This prevents empty fields.&lt;br&gt;
That is helpful for clean output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Address field
&lt;/h2&gt;

&lt;p&gt;If address exists, it builds a PostalAddress object.&lt;br&gt;
It sets [at]type to PostalAddress.&lt;br&gt;
Then it spreads the address fields.&lt;br&gt;
Those fields are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;streetAddress&lt;/li&gt;
&lt;li&gt;addressLocality&lt;/li&gt;
&lt;li&gt;addressRegion&lt;/li&gt;
&lt;li&gt;postalCode&lt;/li&gt;
&lt;li&gt;addressCountry&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ContactPoint field
&lt;/h2&gt;

&lt;p&gt;If contactPoint exists and is not empty, it maps each entry.&lt;br&gt;
Each entry becomes a ContactPoint object.&lt;br&gt;
It sets [at]type to ContactPoint.&lt;br&gt;
Then it spreads the input.&lt;br&gt;
This can represent sales, support, or other contact types.&lt;/p&gt;

&lt;h2&gt;
  
  
  sameAs field
&lt;/h2&gt;

&lt;p&gt;If sameAs exists and is not empty, it adds sameAs.&lt;br&gt;
sameAs is a list of URLs.&lt;br&gt;
Common examples are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Facebook page URL&lt;/li&gt;
&lt;li&gt;Instagram profile URL&lt;/li&gt;
&lt;li&gt;LinkedIn company page URL&lt;/li&gt;
&lt;li&gt;X profile URL&lt;/li&gt;
&lt;li&gt;YouTube channel URL&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SEO value of Organization schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It defines who owns the site.&lt;/li&gt;
&lt;li&gt;It defines your brand name and logo.&lt;/li&gt;
&lt;li&gt;It can connect your brand to social profiles.&lt;/li&gt;
&lt;li&gt;It helps search engines connect content to a publisher.&lt;/li&gt;
&lt;li&gt;It can reduce ambiguity when your brand name is generic.&lt;/li&gt;
&lt;li&gt;It can help create a consistent entity graph.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  WebPage schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;WebPage schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a single web page.&lt;br&gt;
It supports core page metadata.&lt;br&gt;
It can connect the page to a website.&lt;br&gt;
It can connect the page to a publisher.&lt;br&gt;
It can attach a mainEntity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;WebPageSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;inLanguage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;isPartOf&lt;/li&gt;
&lt;li&gt;publisher&lt;/li&gt;
&lt;li&gt;mainEntity&lt;/li&gt;
&lt;li&gt;datePublished&lt;/li&gt;
&lt;li&gt;dateModified&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;The base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type WebPage&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;inLanguage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  isPartOf field
&lt;/h2&gt;

&lt;p&gt;If isPartOf exists, it builds a Website object.&lt;br&gt;
It sets [at]type to Website.&lt;br&gt;
Then it adds url and name.&lt;br&gt;
This connects a page to a website entity.&lt;/p&gt;

&lt;h2&gt;
  
  
  publisher field
&lt;/h2&gt;

&lt;p&gt;If publisher exists, it builds an Organization object.&lt;br&gt;
It sets [at]type to Organization.&lt;br&gt;
It sets name.&lt;br&gt;
It sets logo as an ImageObject.&lt;br&gt;
The logo ImageObject has&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type ImageObject&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  mainEntity field
&lt;/h2&gt;

&lt;p&gt;If mainEntity exists, it attaches it as is.&lt;br&gt;
The type is Record.&lt;br&gt;
This means you can pass any schema object.&lt;br&gt;
For example, you can pass a RealEstateAgent.&lt;br&gt;
Or you can pass an Article.&lt;br&gt;
Or you can pass a FAQPage.&lt;br&gt;
This is flexible.&lt;br&gt;
But it also means you need to validate your own mainEntity.&lt;/p&gt;

&lt;h2&gt;
  
  
  datePublished and dateModified
&lt;/h2&gt;

&lt;p&gt;If provided, they are added directly.&lt;br&gt;
They should be ISO 8601 date strings.&lt;br&gt;
Examples&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2026-02-03&lt;/li&gt;
&lt;li&gt;2026-02-03T10:00:00Z&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SEO value of WebPage schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies the canonical page identity.&lt;/li&gt;
&lt;li&gt;It clarifies language.&lt;/li&gt;
&lt;li&gt;It can connect to a website and publisher.&lt;/li&gt;
&lt;li&gt;It can connect to a main entity.&lt;/li&gt;
&lt;li&gt;It can help search engines interpret page intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  BreadcrumbList schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;BreadcrumbList schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;BreadcrumbList helps search engines understand hierarchy.&lt;br&gt;
It may show breadcrumb rich results.&lt;br&gt;
It can also help with sitelinks context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;BreadcrumbSchemaOptions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;items is an array of name and item URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;The output includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type BreadcrumbList&lt;/li&gt;
&lt;li&gt;itemListElement as an array of ListItem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each ListItem includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type ListItem&lt;/li&gt;
&lt;li&gt;position starting at 1&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;item&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SEO value of BreadcrumbList
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies the user journey.&lt;/li&gt;
&lt;li&gt;It clarifies category and page relationships.&lt;/li&gt;
&lt;li&gt;It can appear in SERP snippets.&lt;/li&gt;
&lt;li&gt;It can reduce URL clutter in results.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  RealEstateAgent schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;RealEstateAgent schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a RealEstateAgent entity.&lt;br&gt;
This is relevant for a real estate platform.&lt;br&gt;
It can be used for company pages or agent profiles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;RealEstateAgentSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;telephone&lt;/li&gt;
&lt;li&gt;email&lt;/li&gt;
&lt;li&gt;priceRange&lt;/li&gt;
&lt;li&gt;address&lt;/li&gt;
&lt;li&gt;geo&lt;/li&gt;
&lt;li&gt;openingHoursSpecification&lt;/li&gt;
&lt;li&gt;sameAs&lt;/li&gt;
&lt;li&gt;areaServed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type RealEstateAgent&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;[at]id equals options.url&lt;/li&gt;
&lt;li&gt;url equals options.url&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a common pattern.&lt;br&gt;
Using [at]id can help connect entities.&lt;/p&gt;

&lt;h2&gt;
  
  
  image field
&lt;/h2&gt;

&lt;p&gt;If image exists, it is added directly.&lt;br&gt;
You should provide an absolute URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  telephone and email
&lt;/h2&gt;

&lt;p&gt;If present, they are added as strings.&lt;/p&gt;

&lt;h2&gt;
  
  
  priceRange
&lt;/h2&gt;

&lt;p&gt;If present, it is added.&lt;br&gt;
It is usually a string like&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$$&lt;/li&gt;
&lt;li&gt;$1000 to $5000&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  address
&lt;/h2&gt;

&lt;p&gt;If present, it becomes a PostalAddress.&lt;br&gt;
Same structure as the Organization address.&lt;/p&gt;

&lt;h2&gt;
  
  
  geo
&lt;/h2&gt;

&lt;p&gt;If present, it becomes GeoCoordinates.&lt;br&gt;
It sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type GeoCoordinates&lt;/li&gt;
&lt;li&gt;latitude&lt;/li&gt;
&lt;li&gt;longitude&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  openingHoursSpecification
&lt;/h2&gt;

&lt;p&gt;If present and non empty, each item becomes OpeningHoursSpecification.&lt;br&gt;
It sets [at]type OpeningHoursSpecification.&lt;br&gt;
Then it spreads the input fields.&lt;br&gt;
Those include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dayOfWeek as an array of strings&lt;/li&gt;
&lt;li&gt;opens&lt;/li&gt;
&lt;li&gt;closes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  sameAs
&lt;/h2&gt;

&lt;p&gt;If present, it is added as a list of URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  areaServed
&lt;/h2&gt;

&lt;p&gt;If present, it becomes a City.&lt;br&gt;
It sets [at]type City.&lt;br&gt;
It sets name.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of RealEstateAgent schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It defines an entity that can be referenced.&lt;/li&gt;
&lt;li&gt;It can support local intent signals.&lt;/li&gt;
&lt;li&gt;It can connect contact details and location.&lt;/li&gt;
&lt;li&gt;It can help clarify the business type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  LocalBusiness schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;LocalBusiness schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a LocalBusiness entity.&lt;br&gt;
This is a generic business listing schema.&lt;br&gt;
It can represent branches or offices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;LocalBusinessSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;telephone&lt;/li&gt;
&lt;li&gt;priceRange&lt;/li&gt;
&lt;li&gt;address&lt;/li&gt;
&lt;li&gt;geo&lt;/li&gt;
&lt;li&gt;openingHoursSpecification&lt;/li&gt;
&lt;li&gt;sameAs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type LocalBusiness&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;[at]id equals url&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional fields are handled similarly to RealEstateAgent.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of LocalBusiness schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It supports local SEO context.&lt;/li&gt;
&lt;li&gt;It provides address and geo coordinates.&lt;/li&gt;
&lt;li&gt;It can support knowledge panel consistency.&lt;/li&gt;
&lt;li&gt;It can connect opening hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Service schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;Service schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a Service.&lt;br&gt;
A Service schema can represent what you offer.&lt;br&gt;
It can connect a service type to a provider.&lt;br&gt;
It can attach offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;ServiceSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serviceType&lt;/li&gt;
&lt;li&gt;provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;areaServed&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;offers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Provider object
&lt;/h2&gt;

&lt;p&gt;provider has&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;logo&lt;/li&gt;
&lt;li&gt;sameAs optional&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type Service&lt;/li&gt;
&lt;li&gt;serviceType&lt;/li&gt;
&lt;li&gt;provider as an Organization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Provider is set to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type Organization&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;logo&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Provider sameAs
&lt;/h2&gt;

&lt;p&gt;If provider.sameAs exists and is non empty, it is attached.&lt;br&gt;
This uses a type cast to edit schema.provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  areaServed
&lt;/h2&gt;

&lt;p&gt;If present, it becomes a Place.&lt;br&gt;
It sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type Place&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  description
&lt;/h2&gt;

&lt;p&gt;If present, it is added.&lt;/p&gt;

&lt;h2&gt;
  
  
  offers
&lt;/h2&gt;

&lt;p&gt;If offers exists, it creates an Offer object.&lt;br&gt;
It sets [at]type Offer.&lt;br&gt;
Then it spreads all fields from offers.&lt;/p&gt;

&lt;p&gt;Offer fields can include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;priceCurrency&lt;/li&gt;
&lt;li&gt;price&lt;/li&gt;
&lt;li&gt;priceSpecification&lt;/li&gt;
&lt;li&gt;availability&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  priceSpecification
&lt;/h2&gt;

&lt;p&gt;If priceSpecification exists, it becomes a PriceSpecification object.&lt;br&gt;
It sets [at]type PriceSpecification.&lt;br&gt;
Then it spreads the priceSpecification fields.&lt;br&gt;
Those fields can include&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;price&lt;/li&gt;
&lt;li&gt;priceCurrency&lt;/li&gt;
&lt;li&gt;validFrom&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SEO value of Service schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies what you do.&lt;/li&gt;
&lt;li&gt;It can connect a service to the provider entity.&lt;/li&gt;
&lt;li&gt;It can expose offer like details.&lt;/li&gt;
&lt;li&gt;It can support better matching to intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  BlogPosting schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;BlogPosting schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function builds BlogPosting structured data.&lt;br&gt;
It is used for blog content.&lt;br&gt;
It can help eligibility for article rich results.&lt;br&gt;
It can help publishers clarify authorship.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;BlogPostingSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mainEntityOfPage.url&lt;/li&gt;
&lt;li&gt;headline&lt;/li&gt;
&lt;li&gt;author.name&lt;/li&gt;
&lt;li&gt;publisher.name&lt;/li&gt;
&lt;li&gt;publisher.logo&lt;/li&gt;
&lt;li&gt;datePublished&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;author.url&lt;/li&gt;
&lt;li&gt;dateModified&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type BlogPosting&lt;/li&gt;
&lt;li&gt;mainEntityOfPage as WebPage with [at]id set to URL&lt;/li&gt;
&lt;li&gt;headline&lt;/li&gt;
&lt;li&gt;author as Person with name&lt;/li&gt;
&lt;li&gt;publisher as Organization with name and logo ImageObject&lt;/li&gt;
&lt;li&gt;datePublished&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conditional fields
&lt;/h2&gt;

&lt;p&gt;If description exists, it is added.&lt;br&gt;
If image exists, it is added.&lt;br&gt;
If author.url exists, author.url is attached.&lt;br&gt;
If dateModified exists, dateModified is attached.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of BlogPosting schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies that content is a blog post.&lt;/li&gt;
&lt;li&gt;It clarifies author and publisher.&lt;/li&gt;
&lt;li&gt;It provides publish and modified dates.&lt;/li&gt;
&lt;li&gt;It helps search engines understand content freshness.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Article schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;Article schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function builds Article structured data.&lt;br&gt;
It is similar to BlogPosting.&lt;br&gt;
It is useful for editorial content and guides.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;ArticleSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mainEntityOfPage.url&lt;/li&gt;
&lt;li&gt;headline&lt;/li&gt;
&lt;li&gt;author.name&lt;/li&gt;
&lt;li&gt;publisher.name&lt;/li&gt;
&lt;li&gt;publisher.logo&lt;/li&gt;
&lt;li&gt;datePublished&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;image string or string array&lt;/li&gt;
&lt;li&gt;author.url&lt;/li&gt;
&lt;li&gt;dateModified&lt;/li&gt;
&lt;li&gt;keywords&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type Article&lt;/li&gt;
&lt;li&gt;mainEntityOfPage WebPage with [at]id&lt;/li&gt;
&lt;li&gt;headline&lt;/li&gt;
&lt;li&gt;author Person&lt;/li&gt;
&lt;li&gt;publisher Organization and ImageObject logo&lt;/li&gt;
&lt;li&gt;datePublished&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Image handling
&lt;/h2&gt;

&lt;p&gt;If image exists, it ensures schema.image is an array.&lt;br&gt;
If the input is already an array, it uses it.&lt;br&gt;
If the input is a string, it wraps it as a single element array.&lt;br&gt;
This is convenient for consumers.&lt;/p&gt;

&lt;h2&gt;
  
  
  keywords
&lt;/h2&gt;

&lt;p&gt;If keywords exists, it is added.&lt;br&gt;
This is a plain string in this implementation.&lt;br&gt;
Sometimes keywords is provided as comma separated.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of Article schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies content type as an article.&lt;/li&gt;
&lt;li&gt;It improves author and publisher clarity.&lt;/li&gt;
&lt;li&gt;It can help with article rich results.&lt;/li&gt;
&lt;li&gt;It supports date signals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SoftwareApplication schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;SoftwareApplication schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a software application.&lt;br&gt;
This is appropriate for a SaaS platform.&lt;br&gt;
It can help search engines understand your product.&lt;br&gt;
It can connect offers and ratings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;SoftwareApplicationSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;applicationCategory&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;author.name&lt;/li&gt;
&lt;li&gt;author.url&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;operatingSystem&lt;/li&gt;
&lt;li&gt;image&lt;/li&gt;
&lt;li&gt;offers&lt;/li&gt;
&lt;li&gt;aggregateRating&lt;/li&gt;
&lt;li&gt;applicationSubCategory&lt;/li&gt;
&lt;li&gt;softwareVersion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type SoftwareApplication&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;applicationCategory&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;url&lt;/li&gt;
&lt;li&gt;author as Organization with name and url&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  operatingSystem
&lt;/h2&gt;

&lt;p&gt;If present, it is attached.&lt;br&gt;
For web apps, you might use Web.&lt;br&gt;
For native apps, you might use iOS or Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  image
&lt;/h2&gt;

&lt;p&gt;If present, it is attached.&lt;br&gt;
Provide an absolute URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  offers
&lt;/h2&gt;

&lt;p&gt;If offers exists, it builds an Offer object.&lt;br&gt;
Offer includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type Offer&lt;/li&gt;
&lt;li&gt;price&lt;/li&gt;
&lt;li&gt;priceCurrency&lt;/li&gt;
&lt;li&gt;availability&lt;/li&gt;
&lt;li&gt;url optional&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  aggregateRating
&lt;/h2&gt;

&lt;p&gt;If present, it becomes AggregateRating.&lt;br&gt;
It sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type AggregateRating&lt;/li&gt;
&lt;li&gt;ratingValue&lt;/li&gt;
&lt;li&gt;ratingCount&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  applicationSubCategory and softwareVersion
&lt;/h2&gt;

&lt;p&gt;If present, they are attached.&lt;br&gt;
These can help describe versions and sub type.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of SoftwareApplication schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It clarifies your product as software.&lt;/li&gt;
&lt;li&gt;It can display pricing and availability.&lt;/li&gt;
&lt;li&gt;It can support rating snippets depending on policy.&lt;/li&gt;
&lt;li&gt;It helps search engines understand app category.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  JobPosting schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;JobPosting schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function describes a job listing.&lt;br&gt;
JobPosting can enable job rich results.&lt;br&gt;
It can help distribute your job posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;JobPostingSchemaOptions&lt;/p&gt;

&lt;p&gt;Required&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;datePosted&lt;/li&gt;
&lt;li&gt;validThrough&lt;/li&gt;
&lt;li&gt;employmentType&lt;/li&gt;
&lt;li&gt;hiringOrganization.name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Optional&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;identifier&lt;/li&gt;
&lt;li&gt;hiringOrganization.sameAs&lt;/li&gt;
&lt;li&gt;hiringOrganization.logo&lt;/li&gt;
&lt;li&gt;jobLocation&lt;/li&gt;
&lt;li&gt;remote&lt;/li&gt;
&lt;li&gt;applicantLocationRequirements&lt;/li&gt;
&lt;li&gt;baseSalary&lt;/li&gt;
&lt;li&gt;responsibilities&lt;/li&gt;
&lt;li&gt;qualifications&lt;/li&gt;
&lt;li&gt;skills&lt;/li&gt;
&lt;li&gt;educationRequirements&lt;/li&gt;
&lt;li&gt;experienceRequirements&lt;/li&gt;
&lt;li&gt;incentiveCompensation&lt;/li&gt;
&lt;li&gt;industry&lt;/li&gt;
&lt;li&gt;jobBenefits&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;p&gt;Base object includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org/" rel="noopener noreferrer"&gt;https://schema.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type JobPosting&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;datePosted&lt;/li&gt;
&lt;li&gt;validThrough&lt;/li&gt;
&lt;li&gt;employmentType&lt;/li&gt;
&lt;li&gt;hiringOrganization as Organization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  identifier
&lt;/h2&gt;

&lt;p&gt;If identifier exists, it becomes PropertyValue.&lt;br&gt;
It sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type PropertyValue&lt;/li&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;value&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  hiringOrganization fields
&lt;/h2&gt;

&lt;p&gt;If sameAs exists, it is attached.&lt;br&gt;
If logo exists, it is attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  jobLocation
&lt;/h2&gt;

&lt;p&gt;If jobLocation exists, it becomes Place with PostalAddress.&lt;/p&gt;

&lt;h2&gt;
  
  
  remote
&lt;/h2&gt;

&lt;p&gt;If remote is provided, it sets schema.remote to a string.&lt;br&gt;
It uses options.remote.toString.&lt;br&gt;
This results in true or false as strings.&lt;br&gt;
Some consumers expect a boolean.&lt;br&gt;
But this is the current behavior.&lt;br&gt;
If you depend on strict schema validation, review this.&lt;/p&gt;

&lt;h2&gt;
  
  
  applicantLocationRequirements
&lt;/h2&gt;

&lt;p&gt;If provided, it becomes a Country object with name.&lt;/p&gt;

&lt;h2&gt;
  
  
  baseSalary
&lt;/h2&gt;

&lt;p&gt;If provided, it builds MonetaryAmount.&lt;br&gt;
It sets&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type MonetaryAmount&lt;/li&gt;
&lt;li&gt;currency&lt;/li&gt;
&lt;li&gt;value as QuantitativeValue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;QuantitativeValue includes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type QuantitativeValue&lt;/li&gt;
&lt;li&gt;unitText&lt;/li&gt;
&lt;li&gt;minValue optional&lt;/li&gt;
&lt;li&gt;maxValue optional&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Responsibilities and other text fields
&lt;/h2&gt;

&lt;p&gt;If provided, they are attached as strings.&lt;br&gt;
This includes responsibilities, qualifications, skills, and more.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of JobPosting schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It can enable job rich results.&lt;/li&gt;
&lt;li&gt;It improves job distribution.&lt;/li&gt;
&lt;li&gt;It clarifies salary and location.&lt;/li&gt;
&lt;li&gt;It clarifies employer identity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  FAQPage schema
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Generator
&lt;/h2&gt;

&lt;p&gt;FAQPage schema generator&lt;/p&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This function creates FAQPage structured data.&lt;br&gt;
FAQ structured data can produce FAQ rich results.&lt;br&gt;
It is often used on landing pages.&lt;br&gt;
It can also be used on documentation pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Input interface
&lt;/h2&gt;

&lt;p&gt;FAQSchemaOptions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;items is an array of question and answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Behavior for empty data
&lt;/h2&gt;

&lt;p&gt;If items is missing or empty, the function returns null.&lt;br&gt;
This is important.&lt;br&gt;
It prevents injecting an empty FAQPage.&lt;br&gt;
It also avoids invalid schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Output shape
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[at]context &lt;a href="https://schema.org" rel="noopener noreferrer"&gt;https://schema.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;[at]type FAQPage&lt;/li&gt;
&lt;li&gt;mainEntity as an array&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each item becomes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[at]type Question&lt;/li&gt;
&lt;li&gt;name set to the question&lt;/li&gt;
&lt;li&gt;acceptedAnswer as Answer&lt;/li&gt;
&lt;li&gt;acceptedAnswer.text set to the answer&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  SEO value of FAQPage schema
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;It answers common questions directly.&lt;/li&gt;
&lt;li&gt;It can expand SERP snippets.&lt;/li&gt;
&lt;li&gt;It can increase click through when implemented correctly.&lt;/li&gt;
&lt;li&gt;It can improve relevance understanding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Helper Current page URL builder
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This helper builds the current page absolute URL.&lt;br&gt;
It uses the route path.&lt;br&gt;
It ensures language prefix is consistent.&lt;br&gt;
It removes locale segments from the route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logic
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;path is route.path&lt;/li&gt;
&lt;li&gt;langPrefix is /en when locale is en&lt;/li&gt;
&lt;li&gt;otherwise langPrefix is empty&lt;/li&gt;
&lt;li&gt;cleanPath removes a leading /en or /ar&lt;/li&gt;
&lt;li&gt;if the route becomes empty, it uses /&lt;/li&gt;
&lt;li&gt;it returns baseUrl + langPrefix + cleanPath&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters for SEO
&lt;/h2&gt;

&lt;p&gt;Absolute URLs are preferred inside schema.&lt;br&gt;
A consistent URL reduces duplicate entity identities.&lt;br&gt;
Locale paths can cause duplicates if not handled.&lt;br&gt;
This helper ensures a stable, localized URL.&lt;/p&gt;

&lt;h1&gt;
  
  
  Helper Breadcrumb builder from route
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Goal
&lt;/h2&gt;

&lt;p&gt;This helper generates breadcrumb items automatically.&lt;br&gt;
It uses route.path.&lt;br&gt;
It splits the path into segments.&lt;br&gt;
It skips locale segments.&lt;br&gt;
It builds cumulative URLs.&lt;br&gt;
It generates readable names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Output
&lt;/h2&gt;

&lt;p&gt;It returns an array of&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first breadcrumb is always Home.&lt;br&gt;
If locale is ar, it uses العربية.&lt;br&gt;
If locale is not ar, it uses Home.&lt;br&gt;
The Home item is baseUrl + /.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name generation details
&lt;/h2&gt;

&lt;p&gt;For each non locale segment&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it splits by hyphen&lt;/li&gt;
&lt;li&gt;it capitalizes the first letter of each word&lt;/li&gt;
&lt;li&gt;it joins with space&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So a segment like property-management becomes&lt;br&gt;
Property Management&lt;/p&gt;

&lt;h2&gt;
  
  
  URL generation details
&lt;/h2&gt;

&lt;p&gt;It builds currentPath incrementally.&lt;br&gt;
It uses langPrefix based on locale.&lt;br&gt;
It builds fullPath as baseUrl + langPrefix + currentPath.&lt;/p&gt;

&lt;p&gt;Then it pushes { name, item }.&lt;/p&gt;

&lt;h1&gt;
  
  
  SEO value of auto breadcrumbs
&lt;/h1&gt;

&lt;p&gt;Even if you render breadcrumbs in UI, schema breadcrumbs help crawlers.&lt;br&gt;
They provide a machine readable hierarchy.&lt;br&gt;
They can reduce ambiguity on nested routes.&lt;br&gt;
They can improve display snippets.&lt;/p&gt;

&lt;h1&gt;
  
  
  Integration guidance
&lt;/h1&gt;

&lt;p&gt;The composable returns generator functions.&lt;br&gt;
A typical usage pattern is&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build schema objects based on page data&lt;/li&gt;
&lt;li&gt;Serialize them to JSON&lt;/li&gt;
&lt;li&gt;Inject into head as JSON LD&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example high level approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;For a homepage

&lt;ul&gt;
&lt;li&gt;Organization&lt;/li&gt;
&lt;li&gt;WebPage&lt;/li&gt;
&lt;li&gt;BreadcrumbList with just Home&lt;/li&gt;
&lt;li&gt;Service or LocalBusiness as mainEntity&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;For a blog post page

&lt;ul&gt;
&lt;li&gt;BlogPosting&lt;/li&gt;
&lt;li&gt;WebPage with mainEntity set to BlogPosting&lt;/li&gt;
&lt;li&gt;BreadcrumbList&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;For a guide page

&lt;ul&gt;
&lt;li&gt;Article&lt;/li&gt;
&lt;li&gt;WebPage with mainEntity set to Article&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;For a FAQ landing page

&lt;ul&gt;
&lt;li&gt;FAQPage&lt;/li&gt;
&lt;li&gt;WebPage with mainEntity set to FAQPage&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;For careers

&lt;ul&gt;
&lt;li&gt;JobPosting&lt;/li&gt;
&lt;li&gt;WebPage with mainEntity set to JobPosting&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Data quality checklist
&lt;/h1&gt;

&lt;p&gt;Use absolute URLs everywhere.&lt;br&gt;
Make sure baseUrl matches your production domain.&lt;br&gt;
Make sure routes generate canonical paths.&lt;br&gt;
Use consistent trailing slash rules.&lt;br&gt;
Do not generate multiple conflicting schemas for the same entity.&lt;br&gt;
Use [at]id consistently when you want to connect entities.&lt;br&gt;
Make sure date strings are valid ISO 8601.&lt;br&gt;
Make sure images are accessible and indexable.&lt;br&gt;
Make sure logos are high quality and stable.&lt;br&gt;
Provide sameAs links that are official.&lt;br&gt;
Avoid placeholder values.&lt;br&gt;
Avoid empty arrays.&lt;br&gt;
Avoid injecting null schema.&lt;/p&gt;

&lt;h1&gt;
  
  
  Common mistakes and how this file avoids them
&lt;/h1&gt;

&lt;p&gt;It only adds optional fields when they exist.&lt;br&gt;
It maps arrays only when they have length.&lt;br&gt;
It wraps Article image into an array.&lt;br&gt;
It returns null for empty FAQ items.&lt;br&gt;
It sets context and type explicitly.&lt;br&gt;
It uses stable baseUrl.&lt;/p&gt;

&lt;h1&gt;
  
  
  Potential improvements you may consider
&lt;/h1&gt;

&lt;p&gt;The JobPosting remote field is a string.&lt;br&gt;
Some schema validators might expect a boolean or a different field.&lt;br&gt;
If you see validation warnings, adjust accordingly.&lt;/p&gt;

&lt;p&gt;The Organization founder field is a string.&lt;br&gt;
Schema.org often allows Person or Organization.&lt;br&gt;
If you need richer founder data, model it as a Person object.&lt;/p&gt;

&lt;p&gt;The composable does not implement WebSite schema.&lt;br&gt;
It uses Website type inside isPartOf.&lt;br&gt;
If you want a full WebSite schema, add a generator.&lt;/p&gt;

&lt;p&gt;The composable does not implement WebSite SearchAction.&lt;br&gt;
If you have a site search, you can add it for sitelinks search box.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing structured data
&lt;/h1&gt;

&lt;p&gt;After you inject JSON LD, test the page.&lt;br&gt;
Use a structured data testing tool.&lt;br&gt;
Validate that required fields exist.&lt;br&gt;
Validate that URLs resolve.&lt;br&gt;
Validate that language matches content.&lt;br&gt;
Validate that breadcrumbs match navigation.&lt;br&gt;
Validate that FAQ matches visible content.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final summary
&lt;/h1&gt;

&lt;p&gt;This module is a structured data factory.&lt;br&gt;
It centralizes Schema.org JSON LD generation.&lt;br&gt;
It supports multiple content types.&lt;br&gt;
It supports localization aware URL helpers.&lt;br&gt;
It supports breadcrumb automation.&lt;br&gt;
Its SEO value comes from clarity.&lt;br&gt;
Clarity supports richer understanding.&lt;br&gt;
Richer understanding supports better presentation.&lt;/p&gt;

&lt;h1&gt;
  
  
  Appendix A Field by field quick reference
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Organization
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
name&lt;br&gt;
url&lt;br&gt;
logo&lt;br&gt;
alternateName&lt;br&gt;
description&lt;br&gt;
founder&lt;br&gt;
foundingDate&lt;br&gt;
foundingLocation&lt;br&gt;
telephone&lt;br&gt;
email&lt;br&gt;
address PostalAddress&lt;br&gt;
contactPoint ContactPoint array&lt;br&gt;
sameAs array&lt;/p&gt;

&lt;h2&gt;
  
  
  WebPage
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
url&lt;br&gt;
name&lt;br&gt;
description&lt;br&gt;
inLanguage&lt;br&gt;
isPartOf Website&lt;br&gt;
publisher Organization with logo ImageObject&lt;br&gt;
mainEntity any schema object&lt;br&gt;
datePublished&lt;br&gt;
dateModified&lt;/p&gt;

&lt;h2&gt;
  
  
  BreadcrumbList
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
itemListElement ListItem array&lt;br&gt;
ListItem position&lt;br&gt;
ListItem name&lt;br&gt;
ListItem item&lt;/p&gt;

&lt;h2&gt;
  
  
  RealEstateAgent
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
name&lt;br&gt;
[at]id&lt;br&gt;
url&lt;br&gt;
image&lt;br&gt;
telephone&lt;br&gt;
email&lt;br&gt;
priceRange&lt;br&gt;
address PostalAddress&lt;br&gt;
geo GeoCoordinates&lt;br&gt;
openingHoursSpecification array&lt;br&gt;
sameAs array&lt;br&gt;
areaServed City&lt;/p&gt;

&lt;h2&gt;
  
  
  LocalBusiness
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
name&lt;br&gt;
[at]id&lt;br&gt;
url&lt;br&gt;
image&lt;br&gt;
telephone&lt;br&gt;
priceRange&lt;br&gt;
address PostalAddress&lt;br&gt;
geo GeoCoordinates&lt;br&gt;
openingHoursSpecification array&lt;br&gt;
sameAs array&lt;/p&gt;

&lt;h2&gt;
  
  
  Service
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
serviceType&lt;br&gt;
provider Organization&lt;br&gt;
provider sameAs&lt;br&gt;
areaServed Place&lt;br&gt;
description&lt;br&gt;
offers Offer&lt;br&gt;
offers priceSpecification PriceSpecification&lt;/p&gt;

&lt;h2&gt;
  
  
  BlogPosting
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
mainEntityOfPage WebPage [at]id&lt;br&gt;
headline&lt;br&gt;
description&lt;br&gt;
image&lt;br&gt;
author Person name and url optional&lt;br&gt;
publisher Organization with logo ImageObject&lt;br&gt;
datePublished&lt;br&gt;
dateModified&lt;/p&gt;

&lt;h2&gt;
  
  
  Article
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
mainEntityOfPage WebPage [at]id&lt;br&gt;
headline&lt;br&gt;
description&lt;br&gt;
image array&lt;br&gt;
author Person&lt;br&gt;
publisher Organization with logo ImageObject&lt;br&gt;
datePublished&lt;br&gt;
dateModified&lt;br&gt;
keywords&lt;/p&gt;

&lt;h2&gt;
  
  
  SoftwareApplication
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
name&lt;br&gt;
applicationCategory&lt;br&gt;
applicationSubCategory&lt;br&gt;
description&lt;br&gt;
url&lt;br&gt;
operatingSystem&lt;br&gt;
image&lt;br&gt;
author Organization&lt;br&gt;
offers Offer&lt;br&gt;
aggregateRating AggregateRating&lt;br&gt;
softwareVersion&lt;/p&gt;

&lt;h2&gt;
  
  
  JobPosting
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
title&lt;br&gt;
description&lt;br&gt;
identifier PropertyValue&lt;br&gt;
datePosted&lt;br&gt;
validThrough&lt;br&gt;
employmentType&lt;br&gt;
hiringOrganization Organization&lt;br&gt;
jobLocation Place with PostalAddress&lt;br&gt;
remote string&lt;br&gt;
applicantLocationRequirements Country&lt;br&gt;
baseSalary MonetaryAmount with QuantitativeValue&lt;br&gt;
responsibilities&lt;br&gt;
qualifications&lt;br&gt;
skills&lt;br&gt;
educationRequirements&lt;br&gt;
experienceRequirements&lt;br&gt;
incentiveCompensation&lt;br&gt;
industry&lt;br&gt;
jobBenefits&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQPage
&lt;/h2&gt;

&lt;p&gt;[at]context&lt;br&gt;
[at]type&lt;br&gt;
mainEntity Question array&lt;br&gt;
Question name&lt;br&gt;
acceptedAnswer Answer&lt;br&gt;
Answer text&lt;/p&gt;

&lt;h1&gt;
  
  
  Appendix B Practical injection pattern
&lt;/h1&gt;

&lt;p&gt;1 Generate the schema object.&lt;br&gt;
2 JSON stringify it.&lt;br&gt;
3 Inject it into a script tag in the page head.&lt;br&gt;
4 Ensure the schema matches what users see.&lt;br&gt;
5 Validate.&lt;br&gt;
6 Monitor search console for enhancements.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nuxt</category>
      <category>seo</category>
    </item>
    <item>
      <title>Why 0.1 + 0.2 !== 0.3 Matters: Engineering Financial Precision in JS</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Sat, 31 Jan 2026 12:01:40 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/why-01-02-03-matters-engineering-financial-precision-in-js-4ofl</link>
      <guid>https://dev.to/ahmed_niazy/why-01-02-03-matters-engineering-financial-precision-in-js-4ofl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz3xt62eq7n510mexcao.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%2Fbz3xt62eq7n510mexcao.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Introduction:&lt;br&gt;
Building a simple web app is easy. Building a mission-critical Enterprise Resource Planning (ERP) system that manages real money, real stock, and real business operations is an entirely different level of engineering. In this deep-dive, we are going to look behind the curtain of "Mehwar," a production-grade ERP system, to see how we solved the hardest challenges in JavaScript.&lt;/p&gt;

&lt;p&gt;Part 1: The Floating Point Nightmare&lt;br&gt;
The biggest mistake a junior developer makes is using native JavaScript arithmetic (+, -, *, /) for money. JavaScript uses IEEE 754 binary floating-point numbers. This means it cannot represent decimals like 0.1 or 0.2 exactly.&lt;/p&gt;

&lt;p&gt;In "Mehwar," we solved this by never allowing raw math. Every calculation goes through a wrapper using Decimal.js.&lt;/p&gt;

&lt;p&gt;Code Sample 1: Precise Tax Addition&lt;br&gt;
function __add_percent(amount, percentage=0) {&lt;br&gt;
    var amount = parseFloat(amount);&lt;br&gt;
    var percentage = isNaN(percentage) ? 0 : parseFloat(percentage);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// We avoid (amount * (1 + percentage/100))
// Instead, we use controlled decimal steps:
var div = Decimal.div(percentage, 100).toNumber();
var mul = Decimal.mul(div, amount).toNumber();
return Decimal.add(amount, mul).toNumber();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Code Sample 2: Back-calculating from Tax-Inclusive Prices&lt;br&gt;
If a product costs $115 including 15% VAT, how do you find the base price? Simple division (115 / 1.15) can lead to rounding drift.&lt;br&gt;
function __get_principle(amount, percentage = 0, minus = false) {&lt;br&gt;
    var amount = parseFloat(amount);&lt;br&gt;
    var percentage = isNaN(percentage) ? 0 : parseFloat(percentage);&lt;br&gt;
    var mul = Decimal.mul(100, amount).toNumber();&lt;br&gt;
    var sum = minus &lt;br&gt;
        ? Decimal.sub(100, percentage).toNumber() &lt;br&gt;
        : Decimal.add(100, percentage).toNumber();&lt;br&gt;
    return Decimal.div(mul, sum).toNumber();&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Part 2: Real-Time UI Synchronization (The POS Engine)&lt;br&gt;
The Point of Sale (POS) is the heart of an ERP. It must be fast, offline-capable, and handle complex logic every time a user presses a key.&lt;/p&gt;

&lt;p&gt;Dynamic Event Binding:&lt;br&gt;
We don't attach event listeners to every row. That would kill memory. Instead, we use event delegation on the table body.&lt;/p&gt;

&lt;p&gt;Code Sample 3: Handling Quantity Changes in Real-time&lt;br&gt;
$('table#pos_table tbody').on('change', 'input.pos_quantity', function () {&lt;br&gt;
    var entered_qty = __read_number($(this));&lt;br&gt;
    var tr = $(this).parents('tr');&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Advanced Check: Sales Rep Stock Allocation
var sales_rep_qty_available = tr.find('input.sales_rep_qty_available').val();
if (sales_rep_qty_available !== undefined &amp;amp;&amp;amp; sales_rep_qty_available !== '') {
    var available_qty = parseFloat(sales_rep_qty_available);
    if (entered_qty &amp;gt; available_qty) {
        toastr.error('Insufficient stock in your van/allocation');
        __write_number($(this), available_qty &amp;gt; 0 ? available_qty : 0);
        entered_qty = available_qty &amp;gt; 0 ? available_qty : 0;
    }
}

// Recalculate everything for this row
pos_each_row(tr);
pos_total_row(); // Global total update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;/p&gt;

&lt;p&gt;Part 3: The Search &amp;amp; Autocomplete Pipeline&lt;br&gt;
When a user scans a barcode, they expect the product to appear in milliseconds. We use a heavily optimized jQuery UI Autocomplete flow.&lt;/p&gt;

&lt;p&gt;Code Sample 4: Intelligent Product Search&lt;br&gt;
$('#search_product').autocomplete({&lt;br&gt;
    source: function (request, response) {&lt;br&gt;
        var price_group = $('#price_group').val();&lt;br&gt;
        $.getJSON('/products/list', {&lt;br&gt;
            price_group: price_group,&lt;br&gt;
            location_id: $('input#location_id').val(),&lt;br&gt;
            term: request.term,&lt;br&gt;
            check_qty: 1&lt;br&gt;
        }, response);&lt;br&gt;
    },&lt;br&gt;
    minLength: 2,&lt;br&gt;
    select: function (event, ui) {&lt;br&gt;
        // Automatic stock validation before adding the row&lt;br&gt;
        if (ui.item.enable_stock != 1 || ui.item.qty_available &amp;gt; 0) {&lt;br&gt;
            pos_product_row(ui.item.variation_id);&lt;br&gt;
        } else {&lt;br&gt;
            alert('Out of stock!');&lt;br&gt;
        }&lt;br&gt;
    }&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Part 4: Global Localization &amp;amp; Formatting Engine&lt;br&gt;
An ERP must speak multiple "languages" (Currency, Date Formats, Thousands separators). In "Mehwar," we created a recursive conversion engine.&lt;/p&gt;

&lt;p&gt;Code Sample 5: Recursive Currency Formatting&lt;br&gt;
function __currency_convert_recursively(element) {&lt;br&gt;
    element.find('.display_currency').each(function() {&lt;br&gt;
        var value = $(this).text();&lt;br&gt;
        var show_symbol = $(this).data('currency_symbol');&lt;br&gt;
        var precision = $(this).data('is_quantity') ? __quantity_precision : __currency_precision;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Uses accounting.js for safe formatting
    $(this).text(accounting.formatMoney(value, __currency_symbol, precision, ...));
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Part 5: User Experience (UX) for Professionals&lt;br&gt;
Business users work in the system 8 hours a day. Micro-UX improvements are essential.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Data Persistence: We use a "Page Leave Confirmation" to prevent accidental data loss.&lt;br&gt;
window.onbeforeunload = function() {&lt;br&gt;
if (form_has_changed) {&lt;br&gt;
    return 'You have unsaved changes. Are you sure you want to leave?';&lt;br&gt;
}&lt;br&gt;
}&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visual Feedback: Numbers change color based on their value (Profit/Loss).&lt;br&gt;
function __highlight(value, obj) {&lt;br&gt;
obj.removeClass('text-success text-danger');&lt;br&gt;
if (value &amp;gt; 0) obj.addClass('text-success');&lt;br&gt;
else if (value &amp;lt; 0) obj.addClass('text-danger');&lt;br&gt;
}&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Part 6: Handling Massive DataTables&lt;br&gt;
In an ERP, listing pages often handle tens of thousands of records. We use DataTables with Server-Side Processing for maximum performance.&lt;/p&gt;

&lt;p&gt;Code Sample 6: Optimized DataTable Ajax Callback&lt;br&gt;
function __datatable_ajax_callback(data){&lt;br&gt;
    for (var i = 0, len = data.columns.length; i &amp;lt; len; i++) {&lt;br&gt;
        // We strip unnecessary data from the request to save bandwidth&lt;br&gt;
        if (! data.columns[i].search.value) delete data.columns[i].search;&lt;br&gt;
        if (data.columns[i].searchable === true) delete data.columns[i].searchable;&lt;br&gt;
        if (data.columns[i].orderable === true) delete data.columns[i].orderable;&lt;br&gt;
    }&lt;br&gt;
    delete data.search.regex;&lt;br&gt;
    return data;&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Part 7: The Modular Plugin System&lt;br&gt;
Instead of loading every library on every page, we use an on-demand initialization strategy.&lt;/p&gt;

&lt;p&gt;Code Sample 7: Dynamic TinyMCE Initialization&lt;br&gt;
function init_tinymce(editor_id) {&lt;br&gt;
    tinymce.init({&lt;br&gt;
        selector: 'textarea#' + editor_id,&lt;br&gt;
        plugins: ['advlist autolink link image lists print preview table'],&lt;br&gt;
        toolbar: 'undo redo | styleselect | bold italic | alignleft aligncenter | bullist numlist',&lt;br&gt;
        menubar: 'favs file edit view insert format tools table help'&lt;br&gt;
    });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Part 8: Advanced Stock Management Logic&lt;br&gt;
Stock calculations must happen on the client-side for immediate feedback, but must match the backend logic exactly.&lt;/p&gt;

&lt;p&gt;Code Sample 8: Unit Multiplier Logic&lt;br&gt;
function __getUnitMultiplier(row){&lt;br&gt;
    multiplier = row.find('select.sub_unit').find(':selected').data('multiplier');&lt;br&gt;
    return (multiplier == undefined) ? 1 : parseFloat(multiplier);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;// When the unit changes, we must recalculate the entire row&lt;br&gt;
$(document).on('change', 'select.sub_unit', function(){&lt;br&gt;
    var tr = $(this).closest('tr');&lt;br&gt;
    var multiplier = __getUnitMultiplier(tr);&lt;br&gt;
    // Logic to update unit price and stock availability based on multiplier&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Part 9: Error Handling and Resilience&lt;br&gt;
When an AJAX call fails (e.g., internet cutout), we must ensure the user doesn't lose data.&lt;/p&gt;

&lt;p&gt;Code Sample 9: Safe Submit Button Handling&lt;br&gt;
function __disable_submit_button(element) {&lt;br&gt;
    // We only disable the button if the user is confirmed to be online&lt;br&gt;
    if (window.navigator.onLine) {&lt;br&gt;
        element.attr('disabled', true);&lt;br&gt;
        element.html(' Processing...');&lt;br&gt;
    } else {&lt;br&gt;
        toastr.error('You are currently offline. Please check your connection.');&lt;br&gt;
    }&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Part 10: State Management without Redux/Vuex&lt;br&gt;
In a legacy-enhanced jQuery environment, we use the DOM itself as our state. This is highly performant for specialized UI like the POS.&lt;/p&gt;

&lt;p&gt;// Our "State" is stored in data-attributes on the rows&lt;br&gt;
// &lt;/p&gt;
&lt;tr&gt;

&lt;p&gt;function sync_state_to_ui(row_id) {&lt;br&gt;
    var tr = $('tr[data-row-id="' + row_id + '"]');&lt;br&gt;
    var qty = tr.data('quantity');&lt;br&gt;
    var price = tr.data('price');&lt;br&gt;
    var total = qty * price;&lt;br&gt;
    tr.find('.total-display').text(total);&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Part 11: Real-time Date and Time Context&lt;br&gt;
ERP systems rely heavily on "when" things happened. We use Moment.js to make these relative and human-readable.&lt;/p&gt;

&lt;p&gt;Code Sample 10: Humanizing Dates Recursively&lt;br&gt;
function __show_date_diff_for_human(element) {&lt;br&gt;
    moment.locale(app_locale);&lt;br&gt;
    element.find('.time-to-now').each(function() {&lt;br&gt;
        var string = $(this).text();&lt;br&gt;
        $(this).text(moment(string).toNow(true));&lt;br&gt;
    });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;Summary:&lt;br&gt;
Building a high-performance ERP requires more than just knowing a language; it requires understanding the domain (Finance, Inventory) and translating that into rock-solid, precise code. By mastering floating-point math, DOM-based state management, and localized formatting, you create a product that can run a multi-million dollar business without missing a single penny.&lt;/p&gt;

&lt;p&gt;Conclusion:&lt;br&gt;
This guide only scratches the surface. Deep-level engineering is found in the edge cases—the offline notifications, the recursive currency conversions, and the millisecond optimizations in search. Keep building, keep measuring, and never settle for "good enough" when money is on the line.&lt;/p&gt;

&lt;h1&gt;
  
  
  SoftwareEngineering #ProjectMehwar #FullStack #EnterpriseApp #JavaScriptMagic #Fintech #SystemArchitecture
&lt;/h1&gt;


&lt;/tr&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>webdev</category>
    </item>
    <item>
      <title>TypeScript-First API Design: Building Type-Safe Systems at Enterprise Scale</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Sat, 31 Jan 2026 11:28:20 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/typescript-first-api-design-building-type-safe-systems-at-enterprise-scale-17bb</link>
      <guid>https://dev.to/ahmed_niazy/typescript-first-api-design-building-type-safe-systems-at-enterprise-scale-17bb</guid>
      <description>&lt;h1&gt;
  
  
  &lt;strong&gt;TypeScript-First API Design: Building Type-Safe Systems at Enterprise Scale&lt;/strong&gt;
&lt;/h1&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%2Fbgcobsk673d433bx3nz4.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%2Fbgcobsk673d433bx3nz4.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction – Why TypeScript Is the Foundation of Safe APIs
&lt;/h2&gt;

&lt;p&gt;At small scale, JavaScript feels liberating. You can move fast, prototype quickly, and ship features with minimal friction. But as systems grow—more teams, more services, more integrations—JavaScript’s flexibility becomes its greatest liability. Nowhere is this more apparent than at &lt;strong&gt;system boundaries&lt;/strong&gt;, especially APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript Fails at Boundaries
&lt;/h3&gt;

&lt;p&gt;APIs are contracts between independently evolving systems. Frontend teams, backend teams, mobile clients, third-party integrators—each moves at a different pace. JavaScript offers &lt;strong&gt;no native mechanism&lt;/strong&gt; to enforce that these parties agree on data shapes, required fields, or error semantics.&lt;/p&gt;

&lt;p&gt;Most production API failures are not caused by complex business logic. They are caused by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing fields&lt;/li&gt;
&lt;li&gt;Renamed properties&lt;/li&gt;
&lt;li&gt;Incorrect nullability assumptions&lt;/li&gt;
&lt;li&gt;Misinterpreted response shapes&lt;/li&gt;
&lt;li&gt;Silent breaking changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are &lt;strong&gt;type mismatches&lt;/strong&gt;, not algorithmic errors.&lt;/p&gt;

&lt;p&gt;JavaScript discovers these mistakes &lt;strong&gt;only at runtime&lt;/strong&gt;, often in production.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Cost of Runtime Errors at Scale
&lt;/h3&gt;

&lt;p&gt;In enterprise systems, runtime API errors are expensive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 Incidents triggered by a single malformed payload&lt;/li&gt;
&lt;li&gt;🧯 Emergency hotfixes across multiple services&lt;/li&gt;
&lt;li&gt;📉 Lost trust between teams&lt;/li&gt;
&lt;li&gt;🕰️ Weeks of defensive coding and regression testing&lt;/li&gt;
&lt;li&gt;😓 Engineers afraid to refactor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a system grows large enough, &lt;strong&gt;fear becomes the bottleneck&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  TypeScript Is Not “Types on Top of JavaScript”
&lt;/h3&gt;

&lt;p&gt;This is the most common misunderstanding.&lt;/p&gt;

&lt;p&gt;TypeScript is not merely JavaScript with annotations. It is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;compile-time reasoning engine&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;constraint system&lt;/strong&gt; for design&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;language for expressing invariants&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;tool for enforcing correctness before code runs&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, TypeScript is a &lt;strong&gt;design tool&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compile-Time Guarantees vs Runtime Failures
&lt;/h3&gt;

&lt;p&gt;Runtime failures are discovered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Late&lt;/li&gt;
&lt;li&gt;By users&lt;/li&gt;
&lt;li&gt;Under load&lt;/li&gt;
&lt;li&gt;In environments you cannot reproduce&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compile-time failures are discovered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immediately&lt;/li&gt;
&lt;li&gt;By the compiler&lt;/li&gt;
&lt;li&gt;During development&lt;/li&gt;
&lt;li&gt;Before merge or deploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every error shifted from runtime to compile time is a &lt;strong&gt;permanent cost reduction&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  APIs as Type Contracts, Not JSON Documents
&lt;/h3&gt;

&lt;p&gt;Traditional API design revolves around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAPI specs&lt;/li&gt;
&lt;li&gt;Swagger docs&lt;/li&gt;
&lt;li&gt;Markdown contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are &lt;strong&gt;descriptive&lt;/strong&gt;, not &lt;strong&gt;enforceable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;TypeScript enables something fundamentally different:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;APIs as executable, enforceable type contracts&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your API contract is a TypeScript type, then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breaking changes fail builds&lt;/li&gt;
&lt;li&gt;Consumers are updated automatically&lt;/li&gt;
&lt;li&gt;Refactoring becomes safe&lt;/li&gt;
&lt;li&gt;Documentation is always correct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article explores how to design APIs where &lt;strong&gt;TypeScript is the primary source of truth&lt;/strong&gt;, and everything else is derived from it.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. TypeScript as an API Design Language
&lt;/h2&gt;

&lt;p&gt;When you adopt a TypeScript-first mindset, APIs stop being “routes returning JSON” and start being &lt;strong&gt;typed interfaces between systems&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Endpoints as Typed Functions
&lt;/h3&gt;

&lt;p&gt;Conceptually, every API endpoint can be modeled as a function:&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="p"&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;RequestType&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;ResponseType&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This framing is powerful because it aligns perfectly with TypeScript’s strengths.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input types define &lt;strong&gt;what is allowed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Output types define &lt;strong&gt;what is guaranteed&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Errors define &lt;strong&gt;what can go wrong&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Requests as Input Types
&lt;/h3&gt;

&lt;p&gt;Request types are not implementation details. They are &lt;strong&gt;contracts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A well-designed request type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevents invalid states&lt;/li&gt;
&lt;li&gt;Encodes business rules&lt;/li&gt;
&lt;li&gt;Forces explicit handling of optionality&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Responses as Output Types
&lt;/h3&gt;

&lt;p&gt;Response types define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What consumers can rely on&lt;/li&gt;
&lt;li&gt;Which fields are stable&lt;/li&gt;
&lt;li&gt;Which fields are nullable or optional&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dramatically reduces defensive coding on the consumer side.&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors as Explicit Unions
&lt;/h3&gt;

&lt;p&gt;In JavaScript, errors are often strings, thrown exceptions, or undocumented shapes.&lt;/p&gt;

&lt;p&gt;In TypeScript-first APIs, errors are &lt;strong&gt;first-class types&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ApiResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiError&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler now enforces that errors are handled.&lt;/p&gt;




&lt;h3&gt;
  
  
  Interfaces vs Type Aliases
&lt;/h3&gt;

&lt;p&gt;Understanding the difference matters at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interfaces&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extendable&lt;/li&gt;
&lt;li&gt;Open for declaration merging&lt;/li&gt;
&lt;li&gt;Ideal for public, extensible contracts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Type aliases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More expressive&lt;/li&gt;
&lt;li&gt;Support unions and intersections&lt;/li&gt;
&lt;li&gt;Ideal for precise modeling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enterprise guideline:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;interfaces&lt;/strong&gt; for stable public DTOs&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;type aliases&lt;/strong&gt; for composition and logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structural Typing: The Hidden Superpower
&lt;/h3&gt;

&lt;p&gt;TypeScript is structurally typed, not nominally typed.&lt;/p&gt;

&lt;p&gt;This means compatibility is based on &lt;strong&gt;shape&lt;/strong&gt;, not explicit inheritance.&lt;/p&gt;

&lt;p&gt;Why this matters for APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent teams can conform to contracts without shared base classes&lt;/li&gt;
&lt;li&gt;Mocking and testing are trivial&lt;/li&gt;
&lt;li&gt;Refactoring internals does not break consumers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Structural typing enables &lt;strong&gt;loose coupling with strong guarantees&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional vs Required Properties
&lt;/h3&gt;

&lt;p&gt;Optionality is not cosmetic. It encodes business meaning.&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;email&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;   &lt;span class="c1"&gt;// may be absent&lt;/span&gt;
&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// explicitly empty&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript forces teams to &lt;strong&gt;decide and document intent&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Readonly API Contracts
&lt;/h3&gt;

&lt;p&gt;API contracts should be immutable:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;email&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents accidental mutation and communicates intent clearly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why &lt;code&gt;any&lt;/code&gt; Breaks the Entire System
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;any&lt;/code&gt; is not a shortcut. It is a &lt;strong&gt;type system escape hatch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;any&lt;/code&gt; enters your API boundary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compile-time guarantees collapse&lt;/li&gt;
&lt;li&gt;Consumers lose safety&lt;/li&gt;
&lt;li&gt;Errors propagate silently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In enterprise systems, &lt;code&gt;any&lt;/code&gt; is a &lt;strong&gt;design failure&lt;/strong&gt;, not a convenience.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Modeling API Requests with TypeScript Types
&lt;/h2&gt;

&lt;p&gt;APIs accept data from the outside world. That data is hostile by default.&lt;/p&gt;

&lt;p&gt;TypeScript allows you to model &lt;strong&gt;exactly&lt;/strong&gt; what your API accepts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing Query Parameters
&lt;/h3&gt;

&lt;p&gt;Query parameters are strings at runtime, but semantically richer.&lt;/p&gt;

&lt;p&gt;Instead of:&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;page&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GetUsersQuery&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;page&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;pageSize&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;disabled&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;This enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compile-time validation&lt;/li&gt;
&lt;li&gt;Automatic narrowing&lt;/li&gt;
&lt;li&gt;IDE autocomplete&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Typing Path Parameters
&lt;/h3&gt;

&lt;p&gt;Path parameters often encode identity:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserPathParams&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using branded types:&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;type&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unique&lt;/span&gt; &lt;span class="nx"&gt;symbol&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;prevents accidental misuse across domains.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typing Request Bodies
&lt;/h3&gt;

&lt;p&gt;Request bodies represent &lt;strong&gt;intent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, creating an order:&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CreateOrderRequest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CustomerId&lt;/span&gt;
  &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadonlyArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ProductId&lt;/span&gt;
    &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Missing fields&lt;/li&gt;
&lt;li&gt;Invalid nesting&lt;/li&gt;
&lt;li&gt;Implicit assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Preventing Invalid States
&lt;/h3&gt;

&lt;p&gt;TypeScript excels at making invalid states unrepresentable:&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;type&lt;/span&gt; &lt;span class="nx"&gt;PaymentMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;cardToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paypal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;paypalId&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler now enforces correctness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Type Narrowing
&lt;/h3&gt;

&lt;p&gt;Control flow analysis ensures safety:&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;card&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cardToken&lt;/span&gt; &lt;span class="c1"&gt;// guaranteed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No runtime checks needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Excess Property Checks
&lt;/h3&gt;

&lt;p&gt;TypeScript rejects extra fields in object literals:&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="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a@b.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;role&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="na"&gt;hack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;strong&gt;huge API safety net&lt;/strong&gt; often overlooked.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. DTOs as TypeScript Contracts (Not Backend Models)
&lt;/h2&gt;

&lt;p&gt;DTOs (Data Transfer Objects) are not database entities. They are &lt;strong&gt;public contracts&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  DTOs as Exported Public Types
&lt;/h3&gt;

&lt;p&gt;DTOs define what the outside world sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;createdAt&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything else is internal.&lt;/p&gt;

&lt;h3&gt;
  
  
  DTOs Are the API Surface
&lt;/h3&gt;

&lt;p&gt;Changing a DTO is a breaking change.&lt;/p&gt;

&lt;p&gt;TypeScript makes this visible immediately across all consumers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Types vs Domain Types vs DTOs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database types&lt;/strong&gt;: persistence-focused&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain types&lt;/strong&gt;: business-logic-focused&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DTOs&lt;/strong&gt;: consumer-focused&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They should &lt;strong&gt;never be the same&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hiding Internal Complexity
&lt;/h3&gt;

&lt;p&gt;DTOs flatten, normalize, and simplify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Domain&lt;/span&gt;
&lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;preferences&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;flags&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// DTO&lt;/span&gt;
&lt;span class="nx"&gt;UserDTO&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript enforces this separation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enforcing Backward Compatibility
&lt;/h3&gt;

&lt;p&gt;When DTOs are types, removing a field breaks builds—not production.&lt;/p&gt;

&lt;p&gt;This enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safe deprecations&lt;/li&gt;
&lt;li&gt;Gradual migrations&lt;/li&gt;
&lt;li&gt;Versioned APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contract-Driven Development with TypeScript
&lt;/h3&gt;

&lt;p&gt;You can design the DTO &lt;strong&gt;before&lt;/strong&gt; implementation.&lt;/p&gt;

&lt;p&gt;The compiler ensures the implementation conforms.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Mapping API Responses Using TypeScript
&lt;/h2&gt;

&lt;p&gt;APIs consume &lt;strong&gt;untrusted data&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Core Problem
&lt;/h3&gt;

&lt;p&gt;External data is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Untyped&lt;/li&gt;
&lt;li&gt;Unvalidated&lt;/li&gt;
&lt;li&gt;Potentially malicious&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TypeScript treats this correctly as &lt;code&gt;unknown&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unknown Until Proven Otherwise
&lt;/h3&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces validation and transformation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mapping to Typed Domain Objects
&lt;/h3&gt;

&lt;p&gt;Instead of trusting shapes, map explicitly:&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;function&lt;/span&gt; &lt;span class="nf"&gt;mapUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&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="c1"&gt;// validate + transform&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once mapped, the rest of the system is safe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transforming Types Safely
&lt;/h3&gt;

&lt;p&gt;Mapping is where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dates become &lt;code&gt;Date&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;IDs become branded types&lt;/li&gt;
&lt;li&gt;Optional fields are normalized&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Guaranteeing Internal Consistency
&lt;/h3&gt;

&lt;p&gt;TypeScript ensures that after mapping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;undefined&lt;/code&gt; surprises&lt;/li&gt;
&lt;li&gt;No missing fields&lt;/li&gt;
&lt;li&gt;No invalid states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isolates risk to the boundary.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Type-Safe Error Modeling in TypeScript
&lt;/h2&gt;

&lt;p&gt;Errors are part of the contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Union Types for Success and Failure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;E&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discriminated Unions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ApiError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&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="s1"&gt;NOT_FOUND&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="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="s1"&gt;UNAUTHORIZED&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;The compiler knows all cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Codes as Literal Types
&lt;/h3&gt;

&lt;p&gt;String literals prevent typos and drift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exhaustive Checking with &lt;code&gt;never&lt;/code&gt;
&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;switch &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="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NOT_FOUND&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;default&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;_exhaustive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a new error is added, the compiler flags every missing handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Strings Are Not Error Handling
&lt;/h3&gt;

&lt;p&gt;Strings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are not enumerable&lt;/li&gt;
&lt;li&gt;Are not enforced&lt;/li&gt;
&lt;li&gt;Drift silently&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Types make errors predictable.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Runtime Validation and TypeScript Boundaries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Fundamental Limitation
&lt;/h3&gt;

&lt;p&gt;TypeScript types do not exist at runtime.&lt;/p&gt;

&lt;p&gt;This is not a flaw—it is a design choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schemas as the Bridge
&lt;/h3&gt;

&lt;p&gt;Schema validation connects runtime data to compile-time types.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zod (TypeScript-First)
&lt;/h3&gt;

&lt;p&gt;Strengths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infers types from schemas&lt;/li&gt;
&lt;li&gt;Excellent DX&lt;/li&gt;
&lt;li&gt;Strong alignment with TS mental model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideal for TS-heavy systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Yup (Less Type-Driven)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Weaker inference&lt;/li&gt;
&lt;li&gt;More runtime-oriented&lt;/li&gt;
&lt;li&gt;Leads to duplication in large systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  io-ts (Advanced, Functional)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Extremely powerful&lt;/li&gt;
&lt;li&gt;Steep learning curve&lt;/li&gt;
&lt;li&gt;Best for FP-heavy teams&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Single Source of Truth
&lt;/h3&gt;

&lt;p&gt;Best practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define schema&lt;/li&gt;
&lt;li&gt;Infer TypeScript type&lt;/li&gt;
&lt;li&gt;Reuse everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No duplication. No drift.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Shared TypeScript Types Across Backend and Frontend
&lt;/h2&gt;

&lt;p&gt;TypeScript enables &lt;strong&gt;end-to-end type safety&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monorepos
&lt;/h3&gt;

&lt;p&gt;Shared packages eliminate contract drift.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared Contracts Packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;company&lt;/span&gt;&lt;span class="sr"&gt;/api-contract&lt;/span&gt;&lt;span class="err"&gt;s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DTOs&lt;/li&gt;
&lt;li&gt;Error types&lt;/li&gt;
&lt;li&gt;Enums&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Versioned Exports
&lt;/h3&gt;

&lt;p&gt;Semantic versioning applies to types too.&lt;/p&gt;

&lt;p&gt;Breaking changes are explicit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enforced Alignment Across Teams
&lt;/h3&gt;

&lt;p&gt;When the backend changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend builds fail&lt;/li&gt;
&lt;li&gt;Mobile builds fail&lt;/li&gt;
&lt;li&gt;Integrations fail early&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Sharing Types Is Good
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Internal platforms&lt;/li&gt;
&lt;li&gt;Unified orgs&lt;/li&gt;
&lt;li&gt;Shared release cadence&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When It Creates Tight Coupling
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Public APIs&lt;/li&gt;
&lt;li&gt;External consumers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TypeScript enforces correctness—but architecture still matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Common TypeScript Anti-Patterns in API Design
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Overusing Generics
&lt;/h3&gt;

&lt;p&gt;Generics add power but reduce readability.&lt;/p&gt;

&lt;p&gt;Avoid generic abstractions that only one team understands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type-Level Overengineering
&lt;/h3&gt;

&lt;p&gt;If your types require a whiteboard, they will be misused.&lt;/p&gt;

&lt;p&gt;Types should clarify intent, not impress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exporting Internal Types
&lt;/h3&gt;

&lt;p&gt;Leaking domain or DB types creates accidental coupling.&lt;/p&gt;

&lt;p&gt;DTOs only.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misusing &lt;code&gt;unknown&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;unknown&lt;/code&gt; is a boundary, not a destination.&lt;/p&gt;

&lt;p&gt;Validate and convert immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treating TypeScript as Documentation Only
&lt;/h3&gt;

&lt;p&gt;If types are optional, ignored, or bypassed—TypeScript is wasted.&lt;/p&gt;

&lt;p&gt;The compiler must be allowed to say &lt;strong&gt;no&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Conclusion – TypeScript as an Enterprise Tool
&lt;/h2&gt;

&lt;p&gt;TypeScript is not a convenience layer.&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;system design language&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;contract enforcement engine&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;scalability multiplier&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When APIs are designed with TypeScript first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Correctness becomes default&lt;/li&gt;
&lt;li&gt;Refactoring becomes safe&lt;/li&gt;
&lt;li&gt;Teams move faster with confidence&lt;/li&gt;
&lt;li&gt;Systems scale without fear&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The compiler becomes a teammate—one that never gets tired and never misses edge cases.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If TypeScript is optional in your API design, correctness is optional too.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At enterprise scale, that is a risk no serious system can afford.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Stop Rebuilding Editors: One Rich Text Editor for Every Framework</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Fri, 23 Jan 2026 22:51:16 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/stop-rebuilding-editors-one-rich-text-editor-for-every-framework-2i0m</link>
      <guid>https://dev.to/ahmed_niazy/stop-rebuilding-editors-one-rich-text-editor-for-every-framework-2i0m</guid>
      <description>&lt;p&gt;🌍 Introducing editor-elsolya — A Universal Rich Text Editor for the Modern Web&lt;/p&gt;

&lt;p&gt;After working across multiple frontend stacks, one problem kept coming back again and again:&lt;/p&gt;

&lt;p&gt;Why do we still need a different editor for every framework?&lt;/p&gt;

&lt;p&gt;Today, I’m excited to introduce editor-elsolya — a framework-agnostic Rich Text Editor, built as a Web Component, designed to run everywhere the web runs.&lt;/p&gt;

&lt;p&gt;🚀 One Editor. Every Framework.&lt;/p&gt;

&lt;p&gt;Install once:&lt;/p&gt;

&lt;p&gt;npm i editor-elsolya&lt;/p&gt;

&lt;p&gt;Use anywhere:&lt;/p&gt;



&lt;p&gt;No wrappers. No framework lock-in. No compromises.&lt;/p&gt;

&lt;p&gt;🧠 Why Web Components?&lt;/p&gt;

&lt;p&gt;editor-elsolya is built as a native Web Component, which means:&lt;/p&gt;

&lt;p&gt;✅ Works with React, Vue, Angular, Nuxt, Next, Svelte, Solid, Astro, and Vanilla JS&lt;/p&gt;

&lt;p&gt;✅ Uses standard HTML &amp;amp; DOM APIs&lt;/p&gt;

&lt;p&gt;✅ Zero dependency on framework internals&lt;/p&gt;

&lt;p&gt;✅ Safe for SSR environments (Next.js / Nuxt)&lt;/p&gt;

&lt;p&gt;✅ Future-proof by web standards, not libraries&lt;/p&gt;

&lt;p&gt;✨ Core Features&lt;/p&gt;

&lt;p&gt;📝 Rich Text Editing powered by contenteditable&lt;/p&gt;

&lt;p&gt;🧩 Native Custom Element: &lt;/p&gt;

&lt;p&gt;🔁 Two-way data flow&lt;/p&gt;

&lt;p&gt;Get / set content via value&lt;/p&gt;

&lt;p&gt;Listen to changes via native CustomEvent&lt;/p&gt;

&lt;p&gt;⚡ Instant integration — no config required&lt;/p&gt;

&lt;p&gt;🔒 Framework-independent architecture&lt;/p&gt;

&lt;p&gt;🧠 Optional Adapters&lt;/p&gt;

&lt;p&gt;React adapter (editor-elsolya/react)&lt;/p&gt;

&lt;p&gt;Vue adapter with v-model support (editor-elsolya/vue)&lt;/p&gt;

&lt;p&gt;🖥 SSR-friendly&lt;/p&gt;

&lt;p&gt;Runs only in the browser&lt;/p&gt;

&lt;p&gt;Safe imports on the server&lt;/p&gt;

&lt;p&gt;🎯 TypeScript-ready&lt;/p&gt;

&lt;p&gt;🪶 Lightweight &amp;amp; performant&lt;/p&gt;

&lt;p&gt;🔌 API Overview&lt;/p&gt;

&lt;p&gt;value: string → get / set editor HTML&lt;/p&gt;

&lt;p&gt;disabled: boolean → enable / disable editing&lt;/p&gt;

&lt;p&gt;Event: change&lt;/p&gt;

&lt;p&gt;e.detail.html&lt;/p&gt;

&lt;p&gt;Pure DOM. No framework magic.&lt;/p&gt;

&lt;p&gt;🏗 Built for Real-World Teams&lt;/p&gt;

&lt;p&gt;This editor is ideal for:&lt;/p&gt;

&lt;p&gt;Teams maintaining multiple frontend stacks&lt;/p&gt;

&lt;p&gt;Design systems &amp;amp; shared UI libraries&lt;/p&gt;

&lt;p&gt;Micro-frontend architectures&lt;/p&gt;

&lt;p&gt;SaaS platforms with evolving tech stacks&lt;/p&gt;

&lt;p&gt;Anyone tired of rewriting editors for every framework&lt;/p&gt;

&lt;p&gt;🛠 Architecture Highlights&lt;/p&gt;

&lt;p&gt;Built on native Web Platform APIs&lt;/p&gt;

&lt;p&gt;No heavy editor engines&lt;/p&gt;

&lt;p&gt;No hidden global state&lt;/p&gt;

&lt;p&gt;Easy to extend (toolbar, themes, plugins)&lt;/p&gt;

&lt;p&gt;Designed for long-term maintainability&lt;/p&gt;

&lt;p&gt;🔮 Roadmap&lt;/p&gt;

&lt;p&gt;Coming next:&lt;/p&gt;

&lt;p&gt;🎨 Theme &amp;amp; CSS variables&lt;/p&gt;

&lt;p&gt;🖼 Image upload support&lt;/p&gt;

&lt;p&gt;🔌 Plugin system&lt;/p&gt;

&lt;p&gt;⚙️ Configurable toolbar&lt;/p&gt;

&lt;p&gt;📦 Smaller bundle &amp;amp; tree-shaking&lt;/p&gt;

&lt;p&gt;🤝 Open Source&lt;/p&gt;

&lt;p&gt;This project is open for feedback, ideas, and contributions.&lt;/p&gt;

&lt;p&gt;If you care about clean architecture, web standards, and developer experience, I’d love to hear your thoughts.&lt;/p&gt;

&lt;p&gt;🔗 Get started&lt;/p&gt;

&lt;p&gt;npm i editor-elsolya&lt;/p&gt;

&lt;p&gt;One editor.&lt;/p&gt;

&lt;p&gt;Every framework.&lt;/p&gt;

&lt;p&gt;Built on web standards.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/editor-elsolya" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/editor-elsolya&lt;/a&gt;&lt;br&gt;
لو المقاله عجبتك ممكن تدعمني هنا &lt;br&gt;
&lt;a href="https://www.linkedin.com/posts/ahmed-niazy-maher-gad-elsolya-506507394_webcomponents-javascript-typescript-activity-7420592395328614400-RTzA?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAGDlLhYBuSmwE3MG1I6cEGDf7QWvWr7KXcw" rel="noopener noreferrer"&gt;https://www.linkedin.com/posts/ahmed-niazy-maher-gad-elsolya-506507394_webcomponents-javascript-typescript-activity-7420592395328614400-RTzA?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAAGDlLhYBuSmwE3MG1I6cEGDf7QWvWr7KXcw&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  WebComponents #JavaScript #TypeScript #FrontendDevelopment
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Frontend #WebDev #NPM #OpenSource
&lt;/h1&gt;

&lt;h1&gt;
  
  
  React #Vue #Angular #Nuxt #NextJS #Svelte #Astro
&lt;/h1&gt;

&lt;h1&gt;
  
  
  MicroFrontends #DesignSystems #SSR
&lt;/h1&gt;

&lt;h1&gt;
  
  
  DeveloperExperience #SoftwareEngineering
&lt;/h1&gt;

&lt;h1&gt;
  
  
  ContentEditable #UIComponents #BuildInPublic
&lt;/h1&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%2Fizbzp2zhkh62kprnzvfu.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%2Fizbzp2zhkh62kprnzvfu.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop Using JS for CSS</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Mon, 08 Dec 2025 06:38:52 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/stop-using-js-for-css-3i6i</link>
      <guid>https://dev.to/ahmed_niazy/stop-using-js-for-css-3i6i</guid>
      <description>&lt;h1&gt;
  
  
  ⭐ &lt;strong&gt;Stop Using JS for CSS — Deep, Detailed Explanation (Pure JS)&lt;/strong&gt;
&lt;/h1&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%2Fipx4ycq8vto1u8149gv1.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%2Fipx4ycq8vto1u8149gv1.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  🔥 &lt;strong&gt;The Core Idea&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JavaScript should &lt;em&gt;not&lt;/em&gt; be used to control layout, styling logic, spacing, colors, animations, or responsiveness — &lt;strong&gt;CSS is already optimized for these tasks&lt;/strong&gt; and is handled directly by the browser engine (e.g., Chrome’s Blink, Safari’s WebKit).&lt;/p&gt;

&lt;p&gt;JavaScript should only control &lt;strong&gt;state&lt;/strong&gt;.&lt;br&gt;
CSS should control &lt;strong&gt;style&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Whenever JS tries to handle style, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lower performance&lt;/li&gt;
&lt;li&gt;layout thrashing&lt;/li&gt;
&lt;li&gt;hard-to-maintain code&lt;/li&gt;
&lt;li&gt;more bugs&lt;/li&gt;
&lt;li&gt;loss of browser optimizations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s break down &lt;strong&gt;the article's arguments in detail&lt;/strong&gt;, with &lt;strong&gt;pure JavaScript examples&lt;/strong&gt;.&lt;/p&gt;


&lt;h1&gt;
  
  
  🧩 &lt;strong&gt;Why CSS Should Handle Style (Not JavaScript)&lt;/strong&gt;
&lt;/h1&gt;
&lt;h2&gt;
  
  
  ### 🔹 1. &lt;strong&gt;CSS handles layout &amp;amp; rendering natively&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Browsers have an optimized rendering engine designed specifically to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout&lt;/li&gt;
&lt;li&gt;box models&lt;/li&gt;
&lt;li&gt;animations&lt;/li&gt;
&lt;li&gt;transitions&lt;/li&gt;
&lt;li&gt;media queries&lt;/li&gt;
&lt;li&gt;responsiveness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CSS runs on the &lt;strong&gt;Compositor Thread&lt;/strong&gt;, not the &lt;strong&gt;Main JS Thread&lt;/strong&gt;.&lt;br&gt;
This means CSS can animate smoothly even at 60fps while JS is doing heavy work.&lt;/p&gt;

&lt;p&gt;When you try to animate or style using JS, everything is forced into the &lt;strong&gt;Main Thread&lt;/strong&gt;, leading to jank and lag.&lt;/p&gt;


&lt;h1&gt;
  
  
  🚫 &lt;strong&gt;JS for styling causes problems&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Let’s go through the article’s main problems explained in depth.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 1 — JavaScript re-renders are expensive&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Changing styles with JS often forces &lt;strong&gt;layout recalculation&lt;/strong&gt;, which is one of the most expensive operations in a browser.&lt;/p&gt;

&lt;p&gt;Example of bad practice:&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="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;200px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;300px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;marginTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;20px&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;Every line here may force the browser to calculate new layout.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 2 — JavaScript overrides browser optimizations&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;CSS has built-in optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cascade&lt;/li&gt;
&lt;li&gt;inheritance&lt;/li&gt;
&lt;li&gt;layered styles&lt;/li&gt;
&lt;li&gt;GPU acceleration&lt;/li&gt;
&lt;li&gt;parallel execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When JS sets styles directly, these optimizations are bypassed.&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// BAD&lt;/span&gt;
&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;translateX(100px)&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;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100px&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;move&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;Much faster and cleaner.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 3 — Mixed responsibilities → unreadable code&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JS is for logic, CSS is for styling.&lt;/p&gt;

&lt;p&gt;When devs mix both in JS files, code becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;harder to read&lt;/li&gt;
&lt;li&gt;harder to debug&lt;/li&gt;
&lt;li&gt;harder to maintain&lt;/li&gt;
&lt;li&gt;harder for teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example of the bad pattern:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#4CAF50&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;borderRadius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;10px&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;CSS should handle this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4CAF50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;btn&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;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 4 — Losing progressive enhancement&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;If styling is tied to JS, and JS fails to load, the website breaks visually.&lt;/p&gt;

&lt;p&gt;HTML + CSS should render correctly &lt;strong&gt;even without JS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If your UI depends on JS to set colors, sizes, spacing… then your site has &lt;em&gt;no fallback&lt;/em&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 5 — JS styling breaks caching&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Browsers cache CSS files.&lt;br&gt;
They &lt;strong&gt;do not&lt;/strong&gt; cache inline JS-generated styles.&lt;/p&gt;

&lt;p&gt;If you rely on JS for layout, the browser must recalculate everything from zero every reload.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 6 — Difficulty overriding styles&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;CSS offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;!important&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;specificity&lt;/li&gt;
&lt;li&gt;layered cascades&lt;/li&gt;
&lt;li&gt;theming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But when JS injects styles inline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"color: red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You cannot override them from CSS easily.&lt;/p&gt;




&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;Problem 7 — JS animations are slower&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JS animation loops like:&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;setInterval&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;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offsetLeft&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&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="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forces layout reflow every 16ms.&lt;/p&gt;

&lt;p&gt;CSS animations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;slide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200px&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="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;slide&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt; &lt;span class="n"&gt;linear&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;CSS animations run on the GPU → smooth.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌟 &lt;strong&gt;What JS &lt;em&gt;should&lt;/em&gt; do instead&lt;/strong&gt;
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🔸 1. Control state
&lt;/h2&gt;

&lt;p&gt;JS handles &lt;strong&gt;state changes&lt;/strong&gt; only.&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 javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is-open&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;CSS handles the style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="m"&gt;.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.box.is-open&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&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;h1&gt;
  
  
  🌟 Pure JavaScript Examples (Correct Way)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  ### Example 1 — Toggle menu
&lt;/h2&gt;

&lt;p&gt;❌ Bad (JS controls styles):&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="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&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;block&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;none&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;✔️ Good (JS controls state):&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="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;open&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#menu&lt;/span&gt;&lt;span class="nc"&gt;.open&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&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;
  
  
  ### Example 2 — Dark mode
&lt;/h2&gt;

&lt;p&gt;❌ Bad:&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#fff&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;✔️ Good:&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.dark&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&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;
  
  
  ### Example 3 — Animate element
&lt;/h2&gt;

&lt;p&gt;❌ Bad:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;setInterval&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;pos&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✔️ Good:&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="nx"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;slide&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.slide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="m"&gt;2s&lt;/span&gt; &lt;span class="n"&gt;linear&lt;/span&gt; &lt;span class="n"&gt;forwards&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@keyframes&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nt"&gt;from&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nt"&gt;to&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200px&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;h1&gt;
  
  
  🌟 Conclusion (Very Important)
&lt;/h1&gt;

&lt;p&gt;The article’s main message:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use JavaScript for:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;state&lt;/li&gt;
&lt;li&gt;events&lt;/li&gt;
&lt;li&gt;data&lt;/li&gt;
&lt;li&gt;logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use CSS for:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;layout&lt;/li&gt;
&lt;li&gt;spacing&lt;/li&gt;
&lt;li&gt;colors&lt;/li&gt;
&lt;li&gt;themes&lt;/li&gt;
&lt;li&gt;animations&lt;/li&gt;
&lt;li&gt;responsiveness&lt;/li&gt;
&lt;li&gt;transitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because CSS is faster, cleaner, and built exactly for this purpose — while JS slows down the browser and increases complexity when used for styling.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mastering SSR, Data Fetching, and No-JavaScript Rendering in Nuxt 4</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Fri, 05 Dec 2025 22:58:53 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/mastering-ssr-data-fetching-and-no-javascript-rendering-in-nuxt-4-22o2</link>
      <guid>https://dev.to/ahmed_niazy/mastering-ssr-data-fetching-and-no-javascript-rendering-in-nuxt-4-22o2</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvg90hbnr9f10gew24msl.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%2Fvg90hbnr9f10gew24msl.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Nuxt 4 is an incredibly powerful framework, especially with its SSR-first architecture powered by Nitro 4. However, many developers run into a frustrating issue:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Skeleton loaders remain visible forever, and real data never appears—especially when JavaScript is disabled.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article is a complete deep-dive into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Nuxt 4 handles SSR&lt;/li&gt;
&lt;li&gt;Why some pages fail when JavaScript is disabled&lt;/li&gt;
&lt;li&gt;Why skeletons get stuck&lt;/li&gt;
&lt;li&gt;How to design fully SSR-compatible pages&lt;/li&gt;
&lt;li&gt;Debugging strategies&lt;/li&gt;
&lt;li&gt;Correct use of &lt;code&gt;useFetch()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Architecture best practices&lt;/li&gt;
&lt;li&gt;Avoiding hydration pitfalls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide is based on real production problems and real solutions.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. Understanding SSR in Nuxt 4&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Nuxt 4 uses &lt;strong&gt;Nitro 4&lt;/strong&gt; for rendering.&lt;br&gt;
SSR means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The server renders the page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useFetch()&lt;/code&gt; runs on the server.&lt;/li&gt;
&lt;li&gt;HTML is generated with data already included.&lt;/li&gt;
&lt;li&gt;Browser receives a fully rendered page.&lt;/li&gt;
&lt;li&gt;If JS is enabled, hydration happens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If JavaScript is disabled, the page should still display complete content — &lt;em&gt;if SSR is implemented correctly&lt;/em&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;3. The Root Cause of Skeleton Loaders Never Disappearing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If your data fetching happens only on the client, you will see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skeleton forever&lt;/li&gt;
&lt;li&gt;No real content&lt;/li&gt;
&lt;li&gt;Empty state&lt;/li&gt;
&lt;li&gt;Hydration errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most commonly caused by:&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;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;$fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;onMounted()&lt;/code&gt; &lt;strong&gt;never runs on the server&lt;/strong&gt;, so SSR produces no content.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Client-Side Fetching vs Server-Side Fetching&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Client-side only:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;$fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✔ Server-side rendering with useFetch():
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pending&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;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server fetching ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data loads before HTML is delivered&lt;/li&gt;
&lt;li&gt;Skeleton disappears automatically&lt;/li&gt;
&lt;li&gt;Page works without JavaScript&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. How Skeleton Loaders Work Internally&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Nuxt skeleton loaders depend on &lt;code&gt;pending&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Skeleton&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"pending"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Content&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;pending&lt;/code&gt; stays &lt;code&gt;true&lt;/code&gt;, skeleton never leaves.&lt;/p&gt;

&lt;p&gt;Reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;useFetch executes on the client&lt;/li&gt;
&lt;li&gt;Hydration mismatch&lt;/li&gt;
&lt;li&gt;Data not fetched before SSR&lt;/li&gt;
&lt;li&gt;Wrong composable structure&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Fixing Skeleton Issues With SSR-First Fetching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Correct SSR-fetching:&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why these options matter:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;server: true&lt;/code&gt;: forces SSR execution&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lazy: false&lt;/code&gt;: ensures fetch runs immediately&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;7. The Architecture Mistake: Fetching Data Inside Components&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Avoid this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- inside a component --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This breaks SSR because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each component re-fetches&lt;/li&gt;
&lt;li&gt;Execution happens after hydration&lt;/li&gt;
&lt;li&gt;SSR doesn’t know about the data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Correct pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch at the page level&lt;/li&gt;
&lt;li&gt;Pass data as props&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;8. Building SSR-Compatible Composables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Bad composable:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useItems&lt;/span&gt; &lt;span class="o"&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;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/items&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;Correct composable:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useItems&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/items&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="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;9. Full SSR-Ready Page Example (Works Without JavaScript)&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;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;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pending&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;useFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/items&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="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ItemSkeleton&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"pending"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ItemCard&lt;/span&gt;
      &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in items"&lt;/span&gt;
      &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item.id"&lt;/span&gt;
      &lt;span class="na"&gt;:item=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renders &lt;strong&gt;instantly&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Works without JavaScript&lt;/li&gt;
&lt;li&gt;Avoids hydration mismatch&lt;/li&gt;
&lt;li&gt;Displays content on first paint&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;10. Understanding Hydration and Why It Breaks UI State&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hydration attaches Vue to SSR-rendered HTML.&lt;/p&gt;

&lt;p&gt;Hydration fails when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR and client outputs don’t match&lt;/li&gt;
&lt;li&gt;State differs between server and client&lt;/li&gt;
&lt;li&gt;Data shape changes&lt;/li&gt;
&lt;li&gt;Skeleton conditions differ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When hydration breaks → UI becomes stuck in loading state.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;11. Debugging SSR Problems Like a Pro&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Technique 1: Disable JavaScript&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If the page breaks → your SSR is not fully implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Technique 2: Verify server execution&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="s2"&gt;Is server?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&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;Technique 3: Check Nuxt DevTools&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;View SSR state flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Technique 4: View page source&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If HTML doesn’t contain data → SSR didn’t run fetch.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;12. Why useFetch() Sometimes Runs on the Client Only&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Common reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Key function depends on client-side values&lt;/li&gt;
&lt;li&gt;Conditional rendering prevents SSR execution&lt;/li&gt;
&lt;li&gt;Missing options: &lt;code&gt;server: true&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Using watchers to trigger fetch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wrong pattern:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;useFetch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`/api/item/&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;value&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SSR does not know &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;13. Nitro’s Role in SSR Data Handling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Nitro handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server file execution&lt;/li&gt;
&lt;li&gt;API routing&lt;/li&gt;
&lt;li&gt;Caching&lt;/li&gt;
&lt;li&gt;Lazy loading&lt;/li&gt;
&lt;li&gt;Edge deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding Nitro helps prevent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unnecessary client-fetches&lt;/li&gt;
&lt;li&gt;Wrong caching behavior&lt;/li&gt;
&lt;li&gt;Inconsistent SSR render&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;14. API Response Design for SSR Stability&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Good SSR-friendly API example:&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineEventHandler&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;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;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example A&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Example B&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guidelines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent keys&lt;/li&gt;
&lt;li&gt;Predictable object structures&lt;/li&gt;
&lt;li&gt;Avoid deeply nested unpredictability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;15. Avoid Suspense Pitfalls&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suspense can break SSR.&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ Wrong:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Suspense&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ChildComponent&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Suspense&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If child fetches → fallback shows forever when JS is disabled.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Correct:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Suspense&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ServerRenderedBlock&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#fallback&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Skeleton&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Suspense&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;16. Managing Large Component Trees in SSR&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch data only once (at page level)&lt;/li&gt;
&lt;li&gt;Pass ready data downward&lt;/li&gt;
&lt;li&gt;Avoid client-side lifecycle hooks for initial load&lt;/li&gt;
&lt;li&gt;Make components stateless regarding initial data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;17. Performance Benefits of SSR-First Design&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;SSR-first yields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster LCP&lt;/li&gt;
&lt;li&gt;Better SEO&lt;/li&gt;
&lt;li&gt;Fully visible first paint&lt;/li&gt;
&lt;li&gt;No empty content&lt;/li&gt;
&lt;li&gt;Smooth hydration&lt;/li&gt;
&lt;li&gt;Better performance on slow devices&lt;/li&gt;
&lt;li&gt;Works without JavaScript entirely&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;18. SSR Testing Checklist&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;✔ Disable JavaScript&lt;br&gt;
✔ Check HTML source for real data&lt;br&gt;
✔ Ensure skeleton disappears&lt;br&gt;
✔ Ensure no hydration warnings&lt;br&gt;
✔ Confirm fetch runs on server&lt;br&gt;
✔ Validate composables return SSR data&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;19. Best Practices Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prefer SSR fetching always&lt;/li&gt;
&lt;li&gt;Avoid data fetching inside components&lt;/li&gt;
&lt;li&gt;Avoid onMounted for initial data&lt;/li&gt;
&lt;li&gt;Use composables sensibly&lt;/li&gt;
&lt;li&gt;Ensure skeleton logic depends on SSR pending&lt;/li&gt;
&lt;li&gt;Test pages with JS disabled&lt;/li&gt;
&lt;li&gt;Ensure API responses are predictable&lt;/li&gt;
&lt;li&gt;Avoid hydration mismatches&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;20. Final Exam (Great for Dev.to Readers)&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q1:&lt;/strong&gt; Why do skeleton loaders remain visible when JavaScript is disabled?
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q2:&lt;/strong&gt; Convert this into SSR-compatible code:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;$fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/list&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;h3&gt;
  
  
  &lt;strong&gt;Q3:&lt;/strong&gt; Write an SSR-first composable using useFetch.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q4:&lt;/strong&gt; Describe what causes hydration mismatch errors.
&lt;/h3&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Q5:&lt;/strong&gt; Build a skeleton fallback pattern that works without JavaScript.
&lt;/h3&gt;




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

&lt;p&gt;SSR in Nuxt 4 is powerful — but only when you understand how to use it correctly.&lt;br&gt;
By adopting an SSR-first architecture, eliminating client-only data fetching, designing stable composables, and structuring your UI for hydration safety, your application becomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster&lt;/li&gt;
&lt;li&gt;More stable&lt;/li&gt;
&lt;li&gt;SEO-optimized&lt;/li&gt;
&lt;li&gt;Accessible&lt;/li&gt;
&lt;li&gt;Fully functional with JavaScript disabled&lt;/li&gt;
&lt;li&gt;Production-ready&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide provides the deep technical understanding needed to achieve that level of reliability in Nuxt 4.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Optimize Like a Pro: Advanced JavaScript Memory Techniques for Large-Scale Projects</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Wed, 03 Dec 2025 08:19:46 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/optimize-like-a-pro-advanced-javascript-memory-techniques-for-large-scale-projects-5cmp</link>
      <guid>https://dev.to/ahmed_niazy/optimize-like-a-pro-advanced-javascript-memory-techniques-for-large-scale-projects-5cmp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2wtsvd3mdiq9ad6at0j.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%2Fu2wtsvd3mdiq9ad6at0j.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A Deep, Extended, Example-Packed Article&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Managing memory properly in JavaScript is one of the most critical skills for building fast, stable, and scalable applications. Whether you're developing a complex frontend interface, a long-running SPA, a Node.js backend, or a real-time system, poor memory handling can cause slowdowns, UI freezes, increased RAM usage, or even total crashes.&lt;/p&gt;

&lt;p&gt;JavaScript has automatic memory management through its garbage collector, but &lt;strong&gt;automatic does NOT mean perfect&lt;/strong&gt;. Incorrect coding patterns will easily prevent the garbage collector from doing its job — resulting in memory leaks and wasted resources.&lt;/p&gt;

&lt;p&gt;This article is a &lt;strong&gt;full deep dive&lt;/strong&gt;, expanded far beyond the standard explanations, with &lt;strong&gt;plenty of examples, patterns, anti-patterns, best practices, and developer tests at the end.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  🔥 &lt;strong&gt;1. Understanding How JavaScript Stores and Frees Memory&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;JavaScript uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stack memory&lt;/strong&gt; → for simple values (numbers, booleans, strings)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heap memory&lt;/strong&gt; → for objects, arrays, functions, DOM nodes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Garbage Collector (GC)&lt;/strong&gt; → automatically frees memory that no longer has references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GC mainly uses &lt;strong&gt;mark-and-sweep&lt;/strong&gt;:&lt;br&gt;
Objects reachable from the global scope are “marked.” Anything unmarked gets removed.&lt;/p&gt;

&lt;p&gt;But here’s the problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you keep even ONE reference to an object, GC CANNOT remove it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is how memory leaks happen.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚠️ &lt;strong&gt;2. The Most Common Memory Leak Sources in JavaScript&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Below are the patterns responsible for 90% of memory leaks developers face — with extended examples.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚨 &lt;strong&gt;2.1. Forgotten Event Listeners&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the biggest leak sources.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Bad Example (Leak)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createButton&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;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Click me&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&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="o"&gt;=&amp;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="s2"&gt;Button clicked&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Later...&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="c1"&gt;// BUT the event listener reference is STILL in memory&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The button is removed from the DOM, but the closure created by the event listener remains in memory.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Fixed Version
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createButton&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;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&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;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;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="s2"&gt;Button clicked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Remove properly&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&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;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;5000&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;
  
  
  🚨 &lt;strong&gt;2.2. Closures That Capture Large Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Closures are powerful — but dangerous when they accidentally retain unnecessary data.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Bad Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeProcessor&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;bigArray&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DATA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="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="nx"&gt;bigArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeProcessor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// bigArray stays alive forever!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Optimized Version
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;makeProcessor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bigArray&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DATA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bigArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;bigArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// release memory&lt;/span&gt;

  &lt;span class="k"&gt;return&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="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="nx"&gt;len&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;
  
  
  🚨 &lt;strong&gt;2.3. Global Variables That Keep Growing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Anything attached to &lt;code&gt;window&lt;/code&gt; or global scope lives &lt;em&gt;forever&lt;/em&gt; unless removed.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Anti-pattern
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&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;item&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;This grows endlessly.&lt;/p&gt;
&lt;h3&gt;
  
  
  ✅ Better
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&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;WeakSet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;WeakSet entries disappear automatically once the object has no other references.&lt;/p&gt;


&lt;h2&gt;
  
  
  🚨 &lt;strong&gt;2.4. Large Arrays That Never Get Emptied&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ❌ Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;list&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="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Later...&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// still might leak in some cases because references remain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Safe Cleanup
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// clears elements in-place&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚨 &lt;strong&gt;2.5. DOM Nodes Stored in Arrays or Objects&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ❌ Bad Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&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;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;elements&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;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// stored forever&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Clean Version
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;render&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;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Don't store DOM nodes globally unless necessary&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  ⚡ &lt;strong&gt;3. Advanced Memory Optimization Techniques&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now we go deeper — these are techniques used in high-performance applications, games, dashboards, and real-time apps.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;3.1. Object Pooling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Instead of creating/destroying objects repeatedly, reuse them.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example: Particle System Without Pooling (Very Slow)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createParticle&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;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;5&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;function&lt;/span&gt; &lt;span class="nf"&gt;loop&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;particle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createParticle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Optimized With Pooling
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pool&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="nx"&gt;size&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="nx"&gt;pool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&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="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;size&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="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;active&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;acquire&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;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;particlePool&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;Pool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;3.2. Using WeakMap and WeakSet for Caches&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Perfect for metadata, temporary states, or per-object settings.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example: Metadata Cache
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;meta&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;WeakMap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;track&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&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="nx"&gt;meta&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="nx"&gt;el&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;If &lt;code&gt;el&lt;/code&gt; is removed from DOM → metadata gets garbage-collected automatically.&lt;/p&gt;


&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;3.3. Debouncing and Throttling High-Frequency Events&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Scrolling, mousemove, resizing → can create tons of allocations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updateUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;3.4. Avoiding Heavy Arrays With Mixed Types&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mixed arrays slow down the engine and increase memory usage.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ Mixed array
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;two&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="na"&gt;three&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Use consistent type patterns
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;3.5. Batch DOM Updates Instead of Repeated Rendering&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ❌ Bad
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ Good
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;frag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createDocumentFragment&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;frag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;frag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  🧩 &lt;strong&gt;4. Memory-Safe Patterns for Large Applications&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Below are patterns specifically for big apps:&lt;/p&gt;


&lt;h2&gt;
  
  
  🟢 &lt;strong&gt;4.1. Unsubscribe EVERYTHING When Components Unmount&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For SPA frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remove event listeners&lt;/li&gt;
&lt;li&gt;Clear intervals&lt;/li&gt;
&lt;li&gt;Clear timeouts&lt;/li&gt;
&lt;li&gt;Cancel API calls&lt;/li&gt;
&lt;li&gt;Close WebSocket connections&lt;/li&gt;
&lt;li&gt;Remove observers (ResizeObserver, IntersectionObserver)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&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;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="s2"&gt;running...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unmount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&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;
  
  
  🟢 &lt;strong&gt;4.2. Split Big Data Into Chunks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Avoid loading massive data at once.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;processInChunks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&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="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&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;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;chunkSize&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="s2"&gt;Processing...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;
  
  
  🟢 &lt;strong&gt;4.3. Lazy-Load Heavy Objects&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Only create heavy objects when they are actually needed.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧪 &lt;strong&gt;5. Developer Self-Test (English Questions)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Use these to test yourself or others.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📝 Section 1: Concept Questions&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What is the difference between stack and heap memory in JavaScript?&lt;/li&gt;
&lt;li&gt;Why can a single remaining reference prevent garbage collection?&lt;/li&gt;
&lt;li&gt;What is a closure memory leak?&lt;/li&gt;
&lt;li&gt;What is the benefit of &lt;code&gt;WeakMap&lt;/code&gt; compared to &lt;code&gt;Map&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;How do event listeners contribute to memory leaks?&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;📝 Section 2: Code Analysis&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Question 1&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Will this cause a memory leak?&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;log&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="s2"&gt;Hello&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;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&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;Question 2&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Where is the leak?&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&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;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;store&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;el&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Question 3&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Fix this:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;create&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;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;big&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20000&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;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="s2"&gt;Hi&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;
  
  
  &lt;strong&gt;📝 Section 3: Practical Tasks&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a function that safely clears an array containing thousands of objects.&lt;/li&gt;
&lt;li&gt;Rewrite a caching system using WeakMap.&lt;/li&gt;
&lt;li&gt;Build a simple object pool for reusing temporary objects.&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%2Fpn2x6t1ch1weh3dmt9tn.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%2Fpn2x6t1ch1weh3dmt9tn.png" alt=" " width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>architecture</category>
      <category>performance</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How JavaScript Handles Memory Under the Hood — A Complete Deep Dive</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Fri, 28 Nov 2025 23:26:19 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/how-javascript-handles-memory-under-the-hood-a-complete-deep-dive-39l5</link>
      <guid>https://dev.to/ahmed_niazy/how-javascript-handles-memory-under-the-hood-a-complete-deep-dive-39l5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3qb3guxyx8un6pr8y4q.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%2Fm3qb3guxyx8un6pr8y4q.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaScript is often described as a “memory-safe” language because it includes a &lt;strong&gt;garbage collector&lt;/strong&gt;, but this doesn’t mean memory problems magically disappear.&lt;br&gt;
In reality, JS developers face memory leaks all the time — especially in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-Page Applications (SPA)&lt;/li&gt;
&lt;li&gt;Real-time dashboards&lt;/li&gt;
&lt;li&gt;Long-lived Node.js servers&lt;/li&gt;
&lt;li&gt;Complex React/Vue/Angular apps&lt;/li&gt;
&lt;li&gt;Components with continuous DOM updates&lt;/li&gt;
&lt;li&gt;Apps that keep state in memory for hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To write robust, scalable, high-performance code, you must understand &lt;strong&gt;exactly&lt;/strong&gt; how JavaScript memory works &lt;em&gt;internally&lt;/em&gt;.&lt;br&gt;
This article will take you from beginner to expert by exploring:&lt;/p&gt;
&lt;h3&gt;
  
  
  ✔ Stack vs Heap
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ Execution Contexts &amp;amp; Call Stack
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ Primitive vs Reference values
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ How JS allocates, uses, and releases memory
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ Mark &amp;amp; Sweep garbage collection
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ Modern garbage collectors (Generational GC, Incremental GC, Concurrent GC)
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ All possible sources of memory leaks
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ How to detect leaks using Chrome DevTools
&lt;/h3&gt;
&lt;h3&gt;
  
  
  ✔ Advanced real-world examples
&lt;/h3&gt;

&lt;p&gt;This is a &lt;strong&gt;complete deep dive&lt;/strong&gt;, not just a simple explanation.&lt;/p&gt;


&lt;h1&gt;
  
  
  🧠 1. The Architecture of JavaScript Memory
&lt;/h1&gt;

&lt;p&gt;JavaScript uses two fundamental memory regions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────┐
│               Stack                 │  → automatic, fast memory
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│                Heap                 │ → dynamic, slow memory
└─────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s break them down &lt;em&gt;in extreme detail&lt;/em&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  🧱 2. Stack Memory — Fast, Predictable, Structured
&lt;/h1&gt;

&lt;p&gt;The stack is a &lt;strong&gt;Last-In-First-Out (LIFO)&lt;/strong&gt; memory system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Push → Push → Push
← Pop ← Pop ← Pop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The stack stores:&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Primitive values
&lt;/h3&gt;

&lt;p&gt;(numbers, strings, booleans, undefined, null, symbols, bigint)&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Function arguments
&lt;/h3&gt;

&lt;p&gt;(even objects are passed as &lt;em&gt;references&lt;/em&gt; stored in stack)&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Execution context
&lt;/h3&gt;

&lt;p&gt;(local variables, this, scope chain)&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Return addresses
&lt;/h3&gt;

&lt;p&gt;(where to go back after a function finishes)&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Pointers to heap objects
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// stored directly in stack&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// copied by value&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alaa&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;Stack memory holds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a → 5
b → 5
obj → (pointer to heap)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heap memory holds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ name: "Alaa" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔥 3. Heap Memory — Dynamic, Flexible, Unpredictable
&lt;/h1&gt;

&lt;p&gt;The heap is a large region used for &lt;strong&gt;objects, arrays, functions, closures&lt;/strong&gt;, and anything dynamic.&lt;/p&gt;

&lt;p&gt;Examples of heap allocation:&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="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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alaa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;   &lt;span class="c1"&gt;// object → heap&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;                    &lt;span class="c1"&gt;// array → heap&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;                         &lt;span class="c1"&gt;// function → heap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The heap is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;larger&lt;/li&gt;
&lt;li&gt;slower&lt;/li&gt;
&lt;li&gt;unstructured&lt;/li&gt;
&lt;li&gt;requires garbage collection&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🏗️ 4. How JavaScript Executes Code (Call Stack + Memory)
&lt;/h1&gt;

&lt;p&gt;To fully understand memory behavior, you must understand the &lt;strong&gt;JavaScript execution model&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌀 Each function call creates an "Execution Context"
&lt;/h2&gt;

&lt;p&gt;Example:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&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;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execution context contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lexical Environment&lt;/li&gt;
&lt;li&gt;Variable Environment&lt;/li&gt;
&lt;li&gt;this binding&lt;/li&gt;
&lt;li&gt;Function arguments&lt;/li&gt;
&lt;li&gt;Reference to outer environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sum EC
├── a = 3  (stack)
├── b = 5  (stack)
└── result = 8 (stack)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔄 5. Memory Lifecycle: Allocation → Usage → Release
&lt;/h1&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Allocation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;JS allocates memory automatically:&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// primitive → stack&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;      &lt;span class="c1"&gt;// reference → stack, object → heap&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Usage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;JS reads or modifies values:&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="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alaa&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;h3&gt;
  
  
  3. &lt;strong&gt;Release&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When values become unreachable, memory should be released.&lt;/p&gt;

&lt;p&gt;But &lt;strong&gt;this is where problems begin&lt;/strong&gt;…&lt;/p&gt;




&lt;h1&gt;
  
  
  🧹 6. Garbage Collection (Mark &amp;amp; Sweep) — Explained in Depth
&lt;/h1&gt;

&lt;p&gt;JavaScript engines like &lt;strong&gt;V8 (Chrome, Node)&lt;/strong&gt; use &lt;strong&gt;Mark &amp;amp; Sweep&lt;/strong&gt; garbage collection.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✔ Step 1 – Mark Phase
&lt;/h3&gt;

&lt;p&gt;Garbage collector identifies “root” objects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global object (&lt;code&gt;window&lt;/code&gt; / &lt;code&gt;global&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Active functions on the call stack&lt;/li&gt;
&lt;li&gt;Closures&lt;/li&gt;
&lt;li&gt;Variables referenced in scope chain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From roots, GC recursively marks all reachable objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Roots
  ├── A (reachable)
  │     └── B (reachable)
  └── C (unreachable) ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✔ Step 2 – Sweep Phase
&lt;/h3&gt;

&lt;p&gt;Unmarked objects are removed from heap.&lt;/p&gt;

&lt;p&gt;This prevents memory from growing indefinitely.&lt;/p&gt;




&lt;h1&gt;
  
  
  🚀 7. Modern Garbage Collectors (Full Professional Understanding)
&lt;/h1&gt;

&lt;p&gt;V8 does not use just one algorithm.&lt;br&gt;
It uses &lt;strong&gt;multiple GC systems working together&lt;/strong&gt;:&lt;/p&gt;
&lt;h2&gt;
  
  
  ✔ 1. Generational Garbage Collection
&lt;/h2&gt;

&lt;p&gt;Heap is divided into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Young generation&lt;/strong&gt; → new small objects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Old generation&lt;/strong&gt; → older, long-lived objects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;New objects die young → cleaned quickly.&lt;br&gt;
Old objects stay → cleaned slowly.&lt;/p&gt;
&lt;h2&gt;
  
  
  ✔ 2. Incremental GC
&lt;/h2&gt;

&lt;p&gt;Large GC operations are split into smaller parts to avoid freezing the UI.&lt;/p&gt;
&lt;h2&gt;
  
  
  ✔ 3. Concurrent GC
&lt;/h2&gt;

&lt;p&gt;GC runs &lt;em&gt;in parallel&lt;/em&gt; with the main thread.&lt;/p&gt;
&lt;h2&gt;
  
  
  ✔ 4. Compaction
&lt;/h2&gt;

&lt;p&gt;Defragments memory to reduce fragmentation.&lt;/p&gt;

&lt;p&gt;All of this happens automatically — but you can still break it.&lt;/p&gt;


&lt;h1&gt;
  
  
  ⚠️ 8. All Types of Memory Leaks in JavaScript (Complete Guide)
&lt;/h1&gt;

&lt;p&gt;Here are the real ways your app leaks memory.&lt;/p&gt;


&lt;h1&gt;
  
  
  🔥 8.1 Leak from Closures Retaining Large Data
&lt;/h1&gt;

&lt;p&gt;This is one of the &lt;strong&gt;most dangerous&lt;/strong&gt; leaks.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;create&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;hugeArray&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="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="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="s2"&gt;Using closure&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though the returned function does not use &lt;code&gt;hugeArray&lt;/code&gt;,&lt;br&gt;
the closure &lt;strong&gt;keeps the entire scope alive&lt;/strong&gt; → leak.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GC cannot remove it&lt;/strong&gt; because the closure is still reachable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Fix:
&lt;/h3&gt;

&lt;p&gt;Move large data outside closure or nullify after use.&lt;/p&gt;


&lt;h1&gt;
  
  
  🔥 8.2 Leaks from setInterval / setTimeout
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setInterval&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;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="s2"&gt;Hi&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="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you never call:&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;clearInterval&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ The closure stays in memory forever.&lt;/p&gt;

&lt;p&gt;Even if the page changes.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔥 8.3 Leaks from Event Listeners Not Removed
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;btn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;btn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&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="o"&gt;=&amp;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="s2"&gt;click&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;If you remove the element:&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="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The listener STILL exists unless removed:&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="nx"&gt;btn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔥 8.4 Leaks from Global Variables
&lt;/h1&gt;

&lt;p&gt;Common mistake:&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="nx"&gt;leaked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// becomes window.leaked → never removed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔥 8.5 Leaks from Forgotten DOM References
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;box&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// but:&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="nx"&gt;div&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// reference keeps it alive!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  🔥 8.6 Leaks from Caches, Maps, WeakMaps
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&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;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;processed&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;p&gt;If &lt;code&gt;obj&lt;/code&gt; should be garbage collected, it won’t be — because it’s stored in a Map.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix:
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;WeakMap&lt;/strong&gt;, not Map.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&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;WeakMap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;WeakMap keys do NOT prevent GC.&lt;/p&gt;




&lt;h1&gt;
  
  
  🌐 8.7 Leaks in Single Page Applications (SPA)
&lt;/h1&gt;

&lt;p&gt;SPAs often leak memory due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;components not fully destroyed&lt;/li&gt;
&lt;li&gt;listeners not removed&lt;/li&gt;
&lt;li&gt;intervals continuing across pages&lt;/li&gt;
&lt;li&gt;references stored inside global state (Vuex, Redux)&lt;/li&gt;
&lt;li&gt;images or canvas objects kept alive&lt;/li&gt;
&lt;li&gt;virtual DOM nodes referencing removed elements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Angular, Vue, React apps suffer from this daily.&lt;/p&gt;




&lt;h1&gt;
  
  
  🔎 9. Detecting Memory Leaks Using Chrome DevTools (Step-by-Step Master Class)
&lt;/h1&gt;

&lt;p&gt;Open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chrome → F12 → Performance or Memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tool 1 — Heap Snapshot
&lt;/h3&gt;

&lt;p&gt;Shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detached DOM nodes&lt;/li&gt;
&lt;li&gt;objects kept alive by closures&lt;/li&gt;
&lt;li&gt;references preventing cleanup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tool 2 — Allocation Timeline
&lt;/h3&gt;

&lt;p&gt;Used to detect memory growth over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool 3 — Live Memory Graph
&lt;/h3&gt;

&lt;p&gt;Used to track leak patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  What to Look For:
&lt;/h3&gt;

&lt;p&gt;✔ Increasing heap after each user action&lt;br&gt;
✔ Detached DOM nodes&lt;br&gt;
✔ Event listeners not removed&lt;br&gt;
✔ Large arrays in closures&lt;br&gt;
✔ setInterval callbacks still active&lt;/p&gt;

&lt;h3&gt;
  
  
  A Real Test:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Take snapshot&lt;/li&gt;
&lt;li&gt;Click around the page&lt;/li&gt;
&lt;li&gt;Take another snapshot&lt;/li&gt;
&lt;li&gt;Heap should return to the same level&lt;/li&gt;
&lt;li&gt;If it grows each time → leak&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  🛠️ 10. Real-World Example: Leaking React Component
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&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;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="s2"&gt;running&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="mi"&gt;1000&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;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// cleanup&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;If cleanup is missing → leak.&lt;/p&gt;




&lt;h1&gt;
  
  
  🛠️ 11. Real-World Example: Node.js Memory Leak
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addUser&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="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cache&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// never removed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Over time (API server running for days), this kills memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix:
&lt;/h3&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LRU Cache&lt;/li&gt;
&lt;li&gt;TTL expiration&lt;/li&gt;
&lt;li&gt;WeakMap&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧵 12. Advanced Example: Leaking Through Closures
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bigObj&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;inner&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="s2"&gt;I keep bigObj alive&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even if you never use &lt;code&gt;bigObj&lt;/code&gt;, it’s still reachable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fix: Clean it manually
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bigObj&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;inner&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="s2"&gt;I keep bigObj alive&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;bigObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// remove heavy reference&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;inner&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;h1&gt;
  
  
  🏁 Final Thoughts — You Are Now an Expert
&lt;/h1&gt;

&lt;p&gt;JavaScript &lt;em&gt;tries&lt;/em&gt; to manage memory for you — but you can absolutely break it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key takeaways:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stack → small, fast, structured&lt;/li&gt;
&lt;li&gt;Heap → large, dynamic, messy&lt;/li&gt;
&lt;li&gt;Execution context is the heart of JS memory&lt;/li&gt;
&lt;li&gt;Closures can accidentally keep &lt;em&gt;entire scopes&lt;/em&gt; in memory&lt;/li&gt;
&lt;li&gt;setInterval, listeners, global vars → biggest leak sources&lt;/li&gt;
&lt;li&gt;SPAs are at high risk of memory leaks&lt;/li&gt;
&lt;li&gt;Chrome DevTools is your best friend&lt;/li&gt;
&lt;li&gt;GC is smart — but not magic&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>computerscience</category>
      <category>javascript</category>
      <category>performance</category>
    </item>
    <item>
      <title>Firebase Composables - قابلة لإعادة الاستخدام</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Sun, 23 Nov 2025 21:15:37 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/firebase-composables-qbl-ld-lstkhdm-p89</link>
      <guid>https://dev.to/ahmed_niazy/firebase-composables-qbl-ld-lstkhdm-p89</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkca8ufsqsdbvyow5mde9.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%2Fkca8ufsqsdbvyow5mde9.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Firebase Composables - قابلة لإعادة الاستخدام
&lt;/h1&gt;

&lt;p&gt;هذه المجموعة من Composables تتيح لك استخدام Firebase بسهولة في أي مشروع Nuxt.js مع تغيير البيانات فقط.&lt;/p&gt;

&lt;h2&gt;
  
  
  📁 الملفات
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;useFirebaseConfig.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;ملف التكوين الأساسي لـ Firebase - يحتوي على الإعدادات الافتراضية.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;useFirebaseCore.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Composable أساسي لـ Firebase - يوفر الوظائف الأساسية للاتصال والخدمات.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;useFirebaseChat.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Composable خاص بالمحادثات - يوفر وظائف المحادثات الفورية.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;code&gt;useFirebaseNotifications.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Composable خاص بالإشعارات - يوفر وظائف الإشعارات الفورية.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;useFirebaseExample.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;مثال على كيفية استخدام جميع Composables معاً.&lt;/p&gt;

&lt;h2&gt;
  
  
  📖 شرح تفصيلي للملفات
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;useFirebaseConfig.ts&lt;/code&gt; - ملف التكوين
&lt;/h3&gt;

&lt;p&gt;هذا الملف يحتوي على جميع واجهات التكوين والإعدادات الافتراضية لـ Firebase.&lt;/p&gt;

&lt;h4&gt;
  
  
  الواجهات (Interfaces):
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;FirebaseConfig&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة تحتوي على جميع بيانات التكوين الأساسية لـ Firebase&lt;/li&gt;
&lt;li&gt;الحقول المطلوبة:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;apiKey&lt;/code&gt;: مفتاح API الخاص بمشروع Firebase&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;authDomain&lt;/code&gt;: نطاق المصادقة (مثل: &lt;code&gt;your-project.firebaseapp.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;projectId&lt;/code&gt;: معرف المشروع&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;storageBucket&lt;/code&gt;: حاوية التخزين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;messagingSenderId&lt;/code&gt;: معرف المرسل للإشعارات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;appId&lt;/code&gt;: معرف التطبيق&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;الحقول الاختيارية:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;measurementId&lt;/code&gt;: معرف القياس (لـ Google Analytics)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;FirestoreConfig&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة لتكوين Firestore&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;collectionPrefix&lt;/code&gt;: بادئة اختيارية لأسماء المجموعات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subCollectionPrefix&lt;/code&gt;: بادئة اختيارية للمجموعات الفرعية&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;RealtimeConfig&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة لتكوين Realtime Database&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;databaseURL&lt;/code&gt;: رابط قاعدة البيانات (مطلوب)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pathPrefix&lt;/code&gt;: بادئة اختيارية للمسارات&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;MessagingConfig&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة لتكوين Cloud Messaging&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vapidKey&lt;/code&gt;: مفتاح VAPID للإشعارات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;defaultNotificationOptions&lt;/code&gt;: خيارات افتراضية للإشعارات (عنوان، أيقونة، شارة، صوت)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  الدالة &lt;code&gt;useFirebaseConfig()&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;ترجع كائن يحتوي على جميع الإعدادات الافتراضية&lt;/li&gt;
&lt;li&gt;يمكن استخدامها مباشرة أو دمجها مع إعدادات مخصصة&lt;/li&gt;
&lt;li&gt;الإعدادات الافتراضية قابلة للتعديل حسب احتياجات المشروع&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. &lt;code&gt;useFirebaseCore.ts&lt;/code&gt; - Composable الأساسي
&lt;/h3&gt;

&lt;p&gt;هذا الملف هو القلب الأساسي لجميع Composables الأخرى. يوفر الوظائف الأساسية لجميع خدمات Firebase.&lt;/p&gt;

&lt;h4&gt;
  
  
  الواجهات:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;FirebaseCoreOptions&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة خيارات التكوين للـ Composable الأساسي&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;config&lt;/code&gt;: تكوين Firebase الأساسي (مطلوب)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;firestoreConfig&lt;/code&gt;: تكوين Firestore (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;realtimeConfig&lt;/code&gt;: تكوين Realtime Database (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;messagingConfig&lt;/code&gt;: تكوين Cloud Messaging (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onAuthStateChanged&lt;/code&gt;: دالة callback عند تغيير حالة المصادقة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onMessageReceived&lt;/code&gt;: دالة callback عند استلام رسالة push&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  الحالة (State):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app&lt;/code&gt;: مرجع لتطبيق Firebase&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth&lt;/code&gt;: خدمة المصادقة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;firestore&lt;/code&gt;: خدمة Firestore&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;database&lt;/code&gt;: خدمة Realtime Database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;messaging&lt;/code&gt;: خدمة Cloud Messaging&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;currentUser&lt;/code&gt;: المستخدم الحالي&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isAuthenticated&lt;/code&gt;: حالة المصادقة (true/false)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isInitialized&lt;/code&gt;: حالة التهيئة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;authLoading&lt;/code&gt;: حالة تحميل المصادقة&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  الوظائف الأساسية:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;المصادقة (Authentication):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initializeFirebase()&lt;/code&gt;: تهيئة Firebase وربط جميع الخدمات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signInAnonymouslyUser()&lt;/code&gt;: تسجيل دخول مجهول&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signInWithEmail(email, password)&lt;/code&gt;: تسجيل دخول بالبريد الإلكتروني&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signOutUser()&lt;/code&gt;: تسجيل الخروج&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Firestore:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;addDocument(collectionName, data)&lt;/code&gt;: إضافة مستند جديد مع إضافة &lt;code&gt;createdAt&lt;/code&gt; و &lt;code&gt;updatedAt&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updateDocument(collectionName, docId, data)&lt;/code&gt;: تحديث مستند مع تحديث &lt;code&gt;updatedAt&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deleteDocument(collectionName, docId)&lt;/code&gt;: حذف مستند&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscribeToCollection(collectionName, callback, constraints)&lt;/code&gt;: الاشتراك في مجموعة مع دعم:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;where&lt;/code&gt;: فلاتر الاستعلام&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;orderBy&lt;/code&gt;: ترتيب النتائج&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;limit&lt;/code&gt;: تحديد عدد النتائج&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Realtime Database:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;setRealtimeData(path, data)&lt;/code&gt;: تعيين بيانات في مسار معين مع إضافة &lt;code&gt;timestamp&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pushRealtimeData(path, data)&lt;/code&gt;: إضافة بيانات جديدة مع توليد مفتاح تلقائي&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updateRealtimeData(path, data)&lt;/code&gt;: تحديث بيانات مع إضافة &lt;code&gt;updatedAt&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;removeRealtimeData(path)&lt;/code&gt;: حذف بيانات من مسار معين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscribeToRealtimeData(path, callback)&lt;/code&gt;: الاشتراك في التغييرات في مسار معين&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud Messaging:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requestNotificationPermission()&lt;/code&gt;: طلب إذن الإشعارات والحصول على token&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;subscribeToMessages(callback)&lt;/code&gt;: الاشتراك في استقبال رسائل push&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;التنظيف:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cleanup()&lt;/code&gt;: تنظيف الموارد (يتم تلقائياً عند إغلاق التطبيق)&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. &lt;code&gt;useFirebaseChat.ts&lt;/code&gt; - Composable المحادثات
&lt;/h3&gt;

&lt;p&gt;هذا الملف يوفر وظائف كاملة لإدارة المحادثات الفورية مع دعم Firestore و Realtime Database.&lt;/p&gt;

&lt;h4&gt;
  
  
  الواجهات:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ChatMessage&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة تمثل رسالة محادثة&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: معرف الرسالة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt;: نص الرسالة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: نوع الرسالة (&lt;code&gt;text&lt;/code&gt; أو &lt;code&gt;attachment&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;senderId&lt;/code&gt;: معرف المرسل&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;senderName&lt;/code&gt;: اسم المرسل (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;senderAvatar&lt;/code&gt;: صورة المرسل (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;roomId&lt;/code&gt;: معرف الغرفة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createdAt&lt;/code&gt;: تاريخ الإنشاء&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updatedAt&lt;/code&gt;: تاريخ التحديث&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isTemp&lt;/code&gt;: هل الرسالة مؤقتة (لـ Optimistic Updates)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;attachments&lt;/code&gt;: مصفوفة المرفقات (اختياري)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ChatRoom&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة تمثل غرفة محادثة&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: معرف الغرفة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: اسم الغرفة (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;participants&lt;/code&gt;: مصفوفة معرفات المشاركين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lastMessage&lt;/code&gt;: آخر رسالة (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lastMessageAt&lt;/code&gt;: تاريخ آخر رسالة (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createdAt&lt;/code&gt;: تاريخ الإنشاء&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updatedAt&lt;/code&gt;: تاريخ التحديث&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;ChatOptions&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة خيارات المحادثات (تمتد من &lt;code&gt;FirebaseCoreOptions&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;الحقول الإضافية:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useRealtime&lt;/code&gt;: استخدام Realtime Database بدلاً من Firestore&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;collectionName&lt;/code&gt;: اسم المجموعة (افتراضي: &lt;code&gt;chats&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onNewMessage&lt;/code&gt;: callback عند استلام رسالة جديدة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onMessageSent&lt;/code&gt;: callback عند إرسال رسالة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onMessageError&lt;/code&gt;: callback عند حدوث خطأ&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onRoomCreated&lt;/code&gt;: callback عند إنشاء غرفة&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  الحالة (State):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;جميع الحالات من &lt;code&gt;useFirebaseCore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;messages&lt;/code&gt;: مصفوفة الرسائل الحالية&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rooms&lt;/code&gt;: مصفوفة الغرف&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;currentRoomId&lt;/code&gt;: معرف الغرفة الحالية&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isSubscribed&lt;/code&gt;: حالة الاشتراك&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  الوظائف:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;إدارة الغرف:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;createRoom(participants, name)&lt;/code&gt;: إنشاء غرفة محادثة جديدة

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;participants&lt;/code&gt;: مصفوفة معرفات المستخدمين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt;: اسم الغرفة (اختياري)&lt;/li&gt;
&lt;li&gt;ترجع معرف الغرفة الجديدة&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;إرسال الرسائل:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sendMessage(roomId, body, type, attachments)&lt;/code&gt;: إرسال رسالة عادية&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sendMessageOptimistic(roomId, body, type, attachments)&lt;/code&gt;: إرسال رسالة مع Optimistic Update

&lt;ul&gt;
&lt;li&gt;تعرض الرسالة فوراً قبل تأكيد الإرسال من السيرفر&lt;/li&gt;
&lt;li&gt;تحذف الرسالة المؤقتة عند استلام الرسالة الحقيقية أو عند فشل الإرسال&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;الاشتراكات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;subscribeToRoom(roomId)&lt;/code&gt;: الاشتراك في رسائل غرفة معينة

&lt;ul&gt;
&lt;li&gt;تحدث &lt;code&gt;messages&lt;/code&gt; تلقائياً عند وصول رسائل جديدة&lt;/li&gt;
&lt;li&gt;ترتيب الرسائل حسب وقت الإنشاء&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;subscribeToUserRooms()&lt;/code&gt;: الاشتراك في جميع غرف المستخدم الحالي

&lt;ul&gt;
&lt;li&gt;تحدث &lt;code&gt;rooms&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;ترتيب الغرف حسب آخر رسالة&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;وظائف مساعدة:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;createTempMessage(body, type, attachments)&lt;/code&gt;: إنشاء رسالة مؤقتة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;loadMessages(messages)&lt;/code&gt;: تحميل رسائل يدوياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clearMessages()&lt;/code&gt;: مسح جميع الرسائل&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getCurrentUserId()&lt;/code&gt;: الحصول على معرف المستخدم الحالي&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;التنظيف:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cleanupChat()&lt;/code&gt;: تنظيف موارد المحادثات فقط&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cleanupAll()&lt;/code&gt;: تنظيف جميع الموارد&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. &lt;code&gt;useFirebaseNotifications.ts&lt;/code&gt; - Composable الإشعارات
&lt;/h3&gt;

&lt;p&gt;هذا الملف يوفر وظائف كاملة لإدارة الإشعارات مع دعم Push Notifications.&lt;/p&gt;

&lt;h4&gt;
  
  
  الواجهات:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;Notification&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة تمثل إشعار&lt;/li&gt;
&lt;li&gt;الحقول:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;: معرف الإشعار&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: عنوان الإشعار&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: نص الإشعار&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: نوع الإشعار (&lt;code&gt;info&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;, &lt;code&gt;warning&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;userId&lt;/code&gt;: معرف المستخدم (اختياري - للإشعارات الخاصة)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: بيانات إضافية (اختياري)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;read&lt;/code&gt;: حالة القراءة (true/false)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createdAt&lt;/code&gt;: تاريخ الإنشاء&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updatedAt&lt;/code&gt;: تاريخ التحديث&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;NotificationOptions&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;واجهة خيارات الإشعارات (تمتد من &lt;code&gt;FirebaseCoreOptions&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;الحقول الإضافية:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useRealtime&lt;/code&gt;: استخدام Realtime Database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;collectionName&lt;/code&gt;: اسم المجموعة (افتراضي: &lt;code&gt;notifications&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onNewNotification&lt;/code&gt;: callback عند استلام إشعار جديد&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onNotificationRead&lt;/code&gt;: callback عند قراءة إشعار&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onNotificationError&lt;/code&gt;: callback عند حدوث خطأ&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  الحالة (State):
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;جميع الحالات من &lt;code&gt;useFirebaseCore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notifications&lt;/code&gt;: مصفوفة الإشعارات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unreadCount&lt;/code&gt;: عدد الإشعارات غير المقروءة (يُحسب تلقائياً)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;isSubscribed&lt;/code&gt;: حالة الاشتراك&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  الوظائف:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;إدارة الإشعارات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;createNotification(title, message, type, userId, data)&lt;/code&gt;: إنشاء إشعار جديد&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt;: عنوان الإشعار (مطلوب)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;message&lt;/code&gt;: نص الإشعار (مطلوب)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt;: نوع الإشعار (افتراضي: &lt;code&gt;info&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;userId&lt;/code&gt;: معرف المستخدم (اختياري - إذا لم يُحدد يستخدم المستخدم الحالي)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: بيانات إضافية (اختياري)&lt;/li&gt;
&lt;li&gt;ترجع معرف الإشعار الجديد&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;markAsRead(notificationId)&lt;/code&gt;: تمييز إشعار كمقروء&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;تحدث &lt;code&gt;unreadCount&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;markAllAsRead()&lt;/code&gt;: تمييز جميع إشعارات المستخدم كمقروءة&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;تحدث جميع الإشعارات المحلية والسيرفر&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;deleteNotification(notificationId)&lt;/code&gt;: حذف إشعار&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;تحدث &lt;code&gt;unreadCount&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;الاشتراكات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;subscribeToUserNotifications()&lt;/code&gt;: الاشتراك في إشعارات المستخدم الحالي فقط&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;تحدث &lt;code&gt;notifications&lt;/code&gt; تلقائياً&lt;/li&gt;
&lt;li&gt;ترتيب الإشعارات حسب تاريخ الإنشاء (الأحدث أولاً)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;subscribeToGeneralNotifications()&lt;/code&gt;: الاشتراك في الإشعارات العامة (بدون &lt;code&gt;userId&lt;/code&gt;)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;للإشعارات التي تظهر لجميع المستخدمين&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Push Notifications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;initializePushNotifications()&lt;/code&gt;: تهيئة Push Notifications&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;تطلب إذن الإشعارات من المتصفح&lt;/li&gt;
&lt;li&gt;ترجع token يمكن إرساله للسيرفر&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;subscribeToPushMessages(callback)&lt;/code&gt;: الاشتراك في استقبال رسائل push&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;يتم استدعاء callback عند استلام رسالة push&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;وظائف مساعدة:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getNotificationsByType(type)&lt;/code&gt;: الحصول على إشعارات بنوع معين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getUnreadNotifications()&lt;/code&gt;: الحصول على جميع الإشعارات غير المقروءة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;loadNotifications(notifications)&lt;/code&gt;: تحميل إشعارات يدوياً&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;addNotification(notification)&lt;/code&gt;: إضافة إشعار يدوياً (للاستخدام المحلي)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;clearNotifications()&lt;/code&gt;: مسح جميع الإشعارات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;updateUnreadCount()&lt;/code&gt;: تحديث عداد الإشعارات غير المقروءة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getCurrentUserId()&lt;/code&gt;: الحصول على معرف المستخدم الحالي&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;التنظيف:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cleanupNotifications()&lt;/code&gt;: تنظيف موارد الإشعارات فقط&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cleanupAll()&lt;/code&gt;: تنظيف جميع الموارد&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. &lt;code&gt;useFirebaseExample.ts&lt;/code&gt; - مثال الاستخدام
&lt;/h3&gt;

&lt;p&gt;هذا الملف يحتوي على مثال كامل يوضح كيفية استخدام جميع Composables معاً في مشروع حقيقي.&lt;/p&gt;

&lt;h4&gt;
  
  
  البنية:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. تكوين Firebase:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// جميع بيانات التكوين&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. تهيئة Composables:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;chatFirebase&lt;/code&gt;: instance من &lt;code&gt;useFirebaseChat&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notificationFirebase&lt;/code&gt;: instance من &lt;code&gt;useFirebaseNotifications&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. وظائف مساعدة للمحادثات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initializeChat()&lt;/code&gt;: تهيئة المحادثات والاشتراك في الغرف&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;joinChatRoom(roomId)&lt;/code&gt;: الانضمام لغرفة محادثة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createChatRoom(participants, name)&lt;/code&gt;: إنشاء غرفة جديدة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sendChatMessage(roomId, messageText)&lt;/code&gt;: إرسال رسالة نصية&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sendChatFile(roomId, fileName, fileType, fileUrl, fileSize)&lt;/code&gt;: إرسال ملف&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. وظائف مساعدة للإشعارات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;initializeNotifications()&lt;/code&gt;: تهيئة الإشعارات والاشتراك&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createNotification(title, message, type, userId, data)&lt;/code&gt;: إنشاء إشعار&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;markNotificationAsRead(notificationId)&lt;/code&gt;: تمييز إشعار كمقروء&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;markAllNotificationsAsRead()&lt;/code&gt;: تمييز الكل كمقروء&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deleteNotification(notificationId)&lt;/code&gt;: حذف إشعار&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. وظائف المصادقة:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;signInAnonymously()&lt;/code&gt;: تسجيل دخول كضيف&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signInWithEmail(email, password)&lt;/code&gt;: تسجيل دخول بالبريد&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;signOut()&lt;/code&gt;: تسجيل الخروج&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. وظائف التنظيف:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cleanupAll()&lt;/code&gt;: تنظيف جميع الموارد&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cleanupChat()&lt;/code&gt;: تنظيف موارد المحادثات فقط&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cleanupNotifications()&lt;/code&gt;: تنظيف موارد الإشعارات فقط&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  القيم المُرجعة:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;حالة المحادثات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;chatMessages&lt;/code&gt;: مصفوفة الرسائل&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatRooms&lt;/code&gt;: مصفوفة الغرف&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatCurrentRoom&lt;/code&gt;: معرف الغرفة الحالية&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatConnected&lt;/code&gt;: حالة الاتصال&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatInitialized&lt;/code&gt;: حالة التهيئة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatLoading&lt;/code&gt;: حالة التحميل&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chatSubscribed&lt;/code&gt;: حالة الاشتراك&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;حالة الإشعارات:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;notifications&lt;/code&gt;: مصفوفة الإشعارات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;unreadCount&lt;/code&gt;: عدد الإشعارات غير المقروءة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notificationConnected&lt;/code&gt;: حالة الاتصال&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notificationInitialized&lt;/code&gt;: حالة التهيئة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notificationLoading&lt;/code&gt;: حالة التحميل&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;notificationSubscribed&lt;/code&gt;: حالة الاشتراك&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;حالة المستخدم:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;currentUser&lt;/code&gt;: بيانات المستخدم الحالي&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;وظائف مساعدة:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getUnreadNotifications()&lt;/code&gt;: الحصول على الإشعارات غير المقروءة&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getNotificationsByType(type)&lt;/code&gt;: الحصول على إشعارات بنوع معين&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getCurrentUserId()&lt;/code&gt;: الحصول على معرف المستخدم&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  مثال الاستخدام في المكون:
&lt;/h4&gt;

&lt;p&gt;يحتوي الملف على مثال كامل في التعليقات يوضح كيفية:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;استيراد واستخدام &lt;code&gt;useFirebaseExample&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;تهيئة Firebase عند تحميل المكون&lt;/li&gt;
&lt;li&gt;إرسال الرسائل والانضمام للغرف&lt;/li&gt;
&lt;li&gt;إدارة الإشعارات&lt;/li&gt;
&lt;li&gt;تنظيف الموارد عند إغلاق المكون&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔍 شرح تفصيلي مع أمثلة عملية
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;code&gt;useFirebaseConfig.ts&lt;/code&gt; - شرح مفصل
&lt;/h3&gt;

&lt;h4&gt;
  
  
  الغرض من الملف:
&lt;/h4&gt;

&lt;p&gt;هذا الملف يحتوي على جميع الواجهات (Interfaces) والإعدادات الافتراضية لـ Firebase. يعمل كملف مرجعي لتحديد أنواع البيانات المستخدمة في جميع الملفات الأخرى.&lt;/p&gt;

&lt;h4&gt;
  
  
  كيف يعمل:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. تعريف الواجهات (TypeScript Interfaces)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;FirebaseConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;apiKey&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="c1"&gt;// مفتاح API - يحصل عليه من Firebase Console&lt;/span&gt;
  &lt;span class="nl"&gt;authDomain&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="c1"&gt;// نطاق المصادقة&lt;/span&gt;
  &lt;span class="nl"&gt;projectId&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="c1"&gt;// معرف المشروع&lt;/span&gt;
  &lt;span class="c1"&gt;// ... إلخ&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 2. دالة ترجع الإعدادات الافتراضية&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;useFirebaseConfig&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_FIREBASE_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&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;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;defaultFirestoreConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;defaultRealtimeConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;defaultMessagingConfig&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  مثال على الاستخدام:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFirebaseConfig&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;./useFirebaseConfig&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&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;defaultConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// دمج الإعدادات الافتراضية مع إعدادات مخصصة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myConfig&lt;/span&gt; &lt;span class="o"&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;defaultConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY_ACTUAL_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-project-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;h4&gt;
  
  
  ملاحظات مهمة:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;جميع الحقول في &lt;code&gt;FirebaseConfig&lt;/code&gt; مطلوبة ما عدا &lt;code&gt;measurementId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;يمكن استخدام &lt;code&gt;FirestoreConfig&lt;/code&gt; لإضافة بادئات لأسماء المجموعات&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RealtimeConfig&lt;/code&gt; يتطلب &lt;code&gt;databaseURL&lt;/code&gt; فقط&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MessagingConfig&lt;/code&gt; يحتوي على خيارات Push Notifications&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. &lt;code&gt;useFirebaseCore.ts&lt;/code&gt; - شرح مفصل
&lt;/h3&gt;

&lt;h4&gt;
  
  
  الغرض من الملف:
&lt;/h4&gt;

&lt;p&gt;هذا الملف هو الأساس لجميع Composables الأخرى. يوفر جميع الوظائف الأساسية لخدمات Firebase (Authentication, Firestore, Realtime Database, Messaging).&lt;/p&gt;

&lt;h4&gt;
  
  
  كيف يعمل خطوة بخطوة:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;الخطوة 1: التهيئة&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializeFirebase&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. إنشاء تطبيق Firebase&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. تهيئة الخدمات&lt;/span&gt;
  &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getAuth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFirestore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. إعداد مستمع حالة المصادقة&lt;/span&gt;
  &lt;span class="nf"&gt;onAuthStateChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&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;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!!&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;الخطوة 2: المصادقة&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// تسجيل دخول مجهول&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signInAnonymouslyUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;result&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="c1"&gt;// يرجع بيانات المستخدم&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// تسجيل دخول بالبريد&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;signInWithEmail&lt;/span&gt; &lt;span class="o"&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;email&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="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&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;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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;result&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;الخطوة 3: Firestore&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// إضافة مستند&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addDocument&lt;/span&gt; &lt;span class="o"&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;collectionName&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DocumentData&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;// إضافة createdAt و updatedAt تلقائياً&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;docRef&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;addDoc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collectionName&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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="nx"&gt;docRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// يرجع مرجع المستند&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في مجموعة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribeToCollection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// إضافة فلاتر&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;where&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;// إرجاع دالة إلغاء الاشتراك&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;onSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;الخطوة 4: Realtime Database&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// إضافة بيانات جديدة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pushRealtimeData&lt;/span&gt; &lt;span class="o"&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;path&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&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;newRef&lt;/span&gt; &lt;span class="o"&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;dbRef&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ينشئ مفتاح تلقائي&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newRef&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timestamp&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="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// يرجع المفتاح التلقائي&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في التغييرات&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribeToRealtimeData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&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="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;onValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&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="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// استدعاء callback عند أي تغيير&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;gt;&lt;/span&gt; &lt;span class="nf"&gt;off&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbRef&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// دالة إلغاء الاشتراك&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  مثال عملي كامل:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFirebaseCore&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;./useFirebaseCore&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;firebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseCore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onAuthStateChanged&lt;/span&gt;&lt;span class="p"&gt;:&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="o"&gt;=&amp;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;المستخدم:&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// تهيئة Firebase&lt;/span&gt;
&lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeFirebase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// تسجيل دخول&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInAnonymouslyUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// إضافة مستند&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addDocument&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="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;أحمد&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ahmed@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في مجموعة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messages&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;snapshot&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;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&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;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;رسالة جديدة:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&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;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;where&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="s1"&gt;read&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="s1"&gt;==&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
    &lt;span class="na"&gt;orderBy&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="s1"&gt;createdAt&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="s1"&gt;desc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
    &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// إلغاء الاشتراك لاحقاً&lt;/span&gt;
&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. &lt;code&gt;useFirebaseChat.ts&lt;/code&gt; - شرح مفصل
&lt;/h3&gt;

&lt;h4&gt;
  
  
  الغرض من الملف:
&lt;/h4&gt;

&lt;p&gt;يوفر نظام محادثات كامل مع دعم الغرف والرسائل الفورية والملفات.&lt;/p&gt;

&lt;h4&gt;
  
  
  كيف يعمل:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. إنشاء غرفة محادثة:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createRoom&lt;/span&gt; &lt;span class="o"&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;participants&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="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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;roomData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;participants&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// مصفوفة معرفات المستخدمين&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;// اسم الغرفة (اختياري)&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// حفظ في Firestore أو Realtime Database&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useRealtime&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;roomId&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;pushRealtimeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats/rooms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;roomData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;docRef&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;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats/rooms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;roomData&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;roomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;docRef&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. إرسال رسالة:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="o"&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;roomId&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;senderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;senderName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;displayName&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// حفظ الرسالة&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useRealtime&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="nf"&gt;pushRealtimeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`chats/rooms/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;addDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`chats/rooms/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// تحديث آخر رسالة في الغرفة&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats/rooms&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;lastMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;lastMessageAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;&lt;strong&gt;3. Optimistic Updates (الرسائل المؤقتة):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMessageOptimistic&lt;/span&gt; &lt;span class="o"&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;roomId&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="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. إنشاء رسالة مؤقتة&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tempMessage&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="s2"&gt;`temp-&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isTemp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ... باقي البيانات&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. إضافة الرسالة المؤقتة فوراً (قبل الإرسال)&lt;/span&gt;
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;tempMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 3. إرسال الرسالة الحقيقية&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageId&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;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 4. حذف الرسالة المؤقتة (الرسالة الحقيقية ستصل عبر الاشتراك)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tempIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tempMessage&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;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tempIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;messageId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="c1"&gt;// 5. في حالة الفشل، حذف الرسالة المؤقتة&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tempIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findIndex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tempMessage&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;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tempIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&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;p&gt;&lt;strong&gt;4. الاشتراك في رسائل الغرفة:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribeToRoom&lt;/span&gt; &lt;span class="o"&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;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;currentRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;roomId&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="nx"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Realtime Database&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribeToRealtimeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`chats/rooms/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// تحويل البيانات من كائن إلى مصفوفة&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messagesArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&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="nf"&gt;map&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;messageData&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;

        &lt;span class="c1"&gt;// ترتيب حسب الوقت&lt;/span&gt;
        &lt;span class="nx"&gt;messagesArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="c1"&gt;// تحديث الحالة&lt;/span&gt;
        &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messagesArray&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="nx"&gt;unsubscribeFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Firestore&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribeToCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`chats/rooms/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/messages`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messagesArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&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="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toDate&lt;/span&gt;&lt;span class="p"&gt;()&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;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}));&lt;/span&gt;

        &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messagesArray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;orderBy&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="s1"&gt;createdAt&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="s1"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="c1"&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;unsubscribeFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;unsubscribe&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;h4&gt;
  
  
  مثال عملي كامل:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFirebaseChat&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;./useFirebaseChat&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;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// استخدام Firestore&lt;/span&gt;
  &lt;span class="na"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onNewMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&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;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;رسالة جديدة:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// تشغيل صوت&lt;/span&gt;
    &lt;span class="nf"&gt;playNotificationSound&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;// تهيئة&lt;/span&gt;
&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeFirebase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInAnonymouslyUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// إنشاء غرفة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;roomId&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;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoom&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="s1"&gt;user1&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="s1"&gt;user2&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="s1"&gt;غرفة المحادثة&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في الغرفة&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToRoom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// إرسال رسالة مع Optimistic Update&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessageOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;مرحباً!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// إرسال ملف&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessageOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="s1"&gt;attachment&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="na"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;document.pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/file.pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024000&lt;/span&gt;
  &lt;span class="p"&gt;}]&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. &lt;code&gt;useFirebaseNotifications.ts&lt;/code&gt; - شرح مفصل
&lt;/h3&gt;

&lt;h4&gt;
  
  
  الغرض من الملف:
&lt;/h4&gt;

&lt;p&gt;يوفر نظام إشعارات كامل مع دعم Push Notifications وعداد الإشعارات غير المقروءة.&lt;/p&gt;

&lt;h4&gt;
  
  
  كيف يعمل:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. إنشاء إشعار:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createNotification&lt;/span&gt; &lt;span class="o"&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;title&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="nx"&gt;message&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="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kd"&gt;type&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;userId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nf"&gt;getCurrentUserId&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// إذا لم يُحدد، يستخدم المستخدم الحالي&lt;/span&gt;
    &lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&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="nx"&gt;useRealtime&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;notificationId&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;pushRealtimeData&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="nx"&gt;notificationData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;docRef&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;addDocument&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="nx"&gt;notificationData&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;notificationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;docRef&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. تمييز إشعار كمقروء:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markAsRead&lt;/span&gt; &lt;span class="o"&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;notificationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// تحديث في قاعدة البيانات&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;useRealtime&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="nf"&gt;updateRealtimeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`notifications/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;notificationId&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="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateDocument&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="nx"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;// تحديث الحالة المحلية&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;notificationId&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="nx"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;&lt;strong&gt;3. الاشتراك في إشعارات المستخدم:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribeToUserNotifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getCurrentUserId&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="nx"&gt;useRealtime&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;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribeToRealtimeData&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// تصفية الإشعارات الخاصة بالمستخدم فقط&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationsArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&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="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notificationData&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;notificationData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt;
          &lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;notificationData&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;notificationData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}));&lt;/span&gt;

        &lt;span class="c1"&gt;// ترتيب حسب التاريخ (الأحدث أولاً)&lt;/span&gt;
        &lt;span class="nx"&gt;notificationsArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notificationsArray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;updateUnreadCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&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;unsubscribeFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Firestore مع فلتر&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unsubscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;subscribeToCollection&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationsArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&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="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toDate&lt;/span&gt;&lt;span class="p"&gt;()&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;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
          &lt;span class="p"&gt;}));&lt;/span&gt;

        &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notificationsArray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;updateUnreadCount&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;where&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="s1"&gt;userId&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="s1"&gt;==&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentUserId&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
        &lt;span class="na"&gt;orderBy&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="s1"&gt;createdAt&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="s1"&gt;desc&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="nx"&gt;unsubscribeFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;unsubscribe&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;&lt;strong&gt;4. تحديث عداد الإشعارات غير المقروءة:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updateUnreadCount&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// حساب عدد الإشعارات غير المقروءة&lt;/span&gt;
  &lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Push Notifications:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializePushNotifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. طلب إذن الإشعارات&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;permission&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;Notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requestPermission&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="nx"&gt;permission&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;granted&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="c1"&gt;// 2. الحصول على token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&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;getToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;vapidKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messagingConfig&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;vapidKey&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;Push token:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// 3. إرسال token للسيرفر لحفظه&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Notification permission denied&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;// الاشتراك في استقبال الرسائل&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribeToPushMessages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;onMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messaging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// استدعاء callback عند استلام رسالة push&lt;/span&gt;
    &lt;span class="nf"&gt;callback&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="c1"&gt;// يمكن إضافة الإشعار إلى القائمة المحلية&lt;/span&gt;
    &lt;span class="nf"&gt;addNotification&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;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageId&lt;/span&gt; &lt;span class="o"&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="nf"&gt;toString&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;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;إشعار جديد&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="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;read&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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;h4&gt;
  
  
  مثال عملي كامل:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFirebaseNotifications&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;./useFirebaseNotifications&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;notifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseNotifications&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;collectionName&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="na"&gt;onNewNotification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&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;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;إشعار جديد:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// إظهار toast notification&lt;/span&gt;
    &lt;span class="nf"&gt;showToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;// تهيئة&lt;/span&gt;
&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeFirebase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInAnonymouslyUser&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في الإشعارات&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToUserNotifications&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// تهيئة Push Notifications&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&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;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializePushNotifications&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="c1"&gt;// إرسال token للسيرفر&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveTokenToServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// الاشتراك في Push Messages&lt;/span&gt;
&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToPushMessages&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="o"&gt;=&amp;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;رسالة push:&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// إنشاء إشعار&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="s1"&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="s1"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// تمييز كمقروء&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAsRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// الحصول على الإشعارات غير المقروءة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;unread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUnreadNotifications&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;غير مقروء:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. &lt;code&gt;useFirebaseExample.ts&lt;/code&gt; - شرح مفصل
&lt;/h3&gt;

&lt;h4&gt;
  
  
  الغرض من الملف:
&lt;/h4&gt;

&lt;p&gt;يوفر مثال كامل يوضح كيفية استخدام جميع Composables معاً في مشروع حقيقي. يعمل كـ wrapper يجمع جميع الوظائف في مكان واحد.&lt;/p&gt;

&lt;h4&gt;
  
  
  كيف يعمل:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. تهيئة Composables:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useFirebaseExample&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// تكوين Firebase&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_FIREBASE_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ... باقي التكوين&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// تهيئة Chat Composable&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onNewMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&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;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;رسالة جديدة:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&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;// تهيئة Notifications Composable&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseNotifications&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;collectionName&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="na"&gt;onNewNotification&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notification&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;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;إشعار جديد:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;notification&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;// ... باقي الكود&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. وظائف مساعدة للمحادثات:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializeChat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. تهيئة Firebase&lt;/span&gt;
  &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeFirebase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. انتظار قليل للاتصال&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&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;// 3. الاشتراك في غرف المستخدم&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToUserRooms&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;تم تهيئة المحادثات بنجاح&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="nx"&gt;sendChatMessage&lt;/span&gt; &lt;span class="o"&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;roomId&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="nx"&gt;messageText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// استخدام sendMessageOptimistic للسرعة&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageId&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;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessageOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;messageText&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;messageId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. وظائف مساعدة للإشعارات:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializeNotifications&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 1. تهيئة Firebase&lt;/span&gt;
  &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeFirebase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. انتظار قليل&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&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;// 3. الاشتراك في إشعارات المستخدم&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeToUserNotifications&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// 4. تهيئة Push Notifications&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializePushNotifications&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;تم تهيئة الإشعارات بنجاح&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;p&gt;&lt;strong&gt;4. إرجاع جميع القيم والوظائف:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// حالة المحادثات&lt;/span&gt;
  &lt;span class="na"&gt;chatMessages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chatRooms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rooms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chatConnected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAuthenticated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// حالة الإشعارات&lt;/span&gt;
  &lt;span class="na"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;notificationFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// حالة المستخدم&lt;/span&gt;
  &lt;span class="na"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;chatFirebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// وظائف المحادثات&lt;/span&gt;
  &lt;span class="nx"&gt;initializeChat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;joinChatRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendChatMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// وظائف الإشعارات&lt;/span&gt;
  &lt;span class="nx"&gt;initializeNotifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createNotification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;markNotificationAsRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// وظائف المصادقة&lt;/span&gt;
  &lt;span class="nx"&gt;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signInWithEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// وظائف التنظيف&lt;/span&gt;
  &lt;span class="nx"&gt;cleanupAll&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  مثال عملي كامل في Vue Component:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- حالة الاتصال --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"chatLoading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;جاري التحميل...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-else-if=&lt;/span&gt;&lt;span class="s"&gt;"chatConnected"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;متصل ✅&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-else&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;غير متصل ❌&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- غرف المحادثة --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"rooms"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; 
        &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"room in chatRooms"&lt;/span&gt; 
        &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"room.id"&lt;/span&gt;
        &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"joinRoom(room.id)"&lt;/span&gt;
        &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ active: chatCurrentRoom === room.id }"
      &amp;gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;`غرفة ${room.id&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;room.lastMessage&lt;/span&gt;&lt;span class="dl"&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;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&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;/div&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;messages&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;div&lt;/span&gt; 
        &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message in chatMessages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
        &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ temp: message.isTemp &lt;/span&gt;&lt;span class="err"&gt;}&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;strong&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;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;senderName&lt;/span&gt; &lt;span class="si"&gt;}}&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;/strong&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;span&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.isTemp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;جاري&lt;/span&gt; &lt;span class="nx"&gt;الإرسال&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;/span&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;/div&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;إرسال&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;send-message&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;input&lt;/span&gt; 
        &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
        &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;keyup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enter&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&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="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;إرسال&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notifications&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;header&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;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;الإشعارات&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&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="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;badge&lt;/span&gt;&lt;span class="dl"&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;unreadCount&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&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="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markAllAsRead&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;تمييز&lt;/span&gt; &lt;span class="nx"&gt;الكل&lt;/span&gt; &lt;span class="nx"&gt;كمقروء&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&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="nx"&gt;div&lt;/span&gt; 
        &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification in notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
        &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{ unread: !notification.read &lt;/span&gt;&lt;span class="err"&gt;}&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;h4&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;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h4&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="nx"&gt;p&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;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&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="nx"&gt;button&lt;/span&gt; 
          &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;!notification.read&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
          &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markAsRead(notification.id)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nx"&gt;تمييز&lt;/span&gt; &lt;span class="nx"&gt;كمقروء&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&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;/div&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;/div&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;/template&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="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&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="nx"&gt;useFirebaseExample&lt;/span&gt; &lt;span class="err"&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;@/composables/useFirebaseExample&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="c1"&gt;// الحالة&lt;/span&gt;
  &lt;span class="nx"&gt;chatMessages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatRooms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatCurrentRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatConnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="c1"&gt;// الوظائف&lt;/span&gt;
  &lt;span class="nx"&gt;initializeChat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;joinChatRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendChatMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initializeNotifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createNotification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;markNotificationAsRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;markAllNotificationsAsRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cleanupAll&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseExample&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;newMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&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;selectedRoomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// تهيئة عند تحميل المكون&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. تسجيل الدخول&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. تهيئة المحادثات والإشعارات معاً&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="nf"&gt;initializeChat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="nf"&gt;initializeNotifications&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;تم التهيئة بنجاح&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;خطأ في التهيئة:&lt;/span&gt;&lt;span class="dl"&gt;'&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="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// الانضمام لغرفة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;joinRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;joinChatRoom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// إرسال رسالة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendChatMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// مسح الحقل&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;خطأ في إرسال الرسالة:&lt;/span&gt;&lt;span class="dl"&gt;'&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="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// تمييز إشعار كمقروء&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markAsRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;markNotificationAsRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// تمييز الكل كمقروء&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markAllAsRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;markAllNotificationsAsRead&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// تنظيف عند إغلاق المكون&lt;/span&gt;
&lt;span class="nf"&gt;onUnmounted&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="nf"&gt;cleanupAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;}&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;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 كيفية الاستخدام
&lt;/h2&gt;

&lt;h3&gt;
  
  
  الخطوة 1: تثبيت Firebase
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;firebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  الخطوة 2: نسخ الملفات
&lt;/h3&gt;

&lt;p&gt;انسخ جميع الملفات من مجلد &lt;code&gt;composables&lt;/code&gt; إلى مشروعك.&lt;/p&gt;

&lt;h3&gt;
  
  
  الخطوة 3: تعديل التكوين
&lt;/h3&gt;

&lt;p&gt;في ملف &lt;code&gt;useFirebaseExample.ts&lt;/code&gt; أو في ملف التكوين الخاص بك:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FirebaseConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_FIREBASE_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;authDomain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-project.firebaseapp.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;projectId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-project-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;storageBucket&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-project.appspot.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messagingSenderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123456789&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1:123456789:web:abcdef123456&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;measurementId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;G-XXXXXXXXXX&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;h3&gt;
  
  
  الخطوة 4: الاستخدام في المكون
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- حالة الاتصال --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"connection-status"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;:class=&lt;/span&gt;&lt;span class="s"&gt;"chatConnected ? 'connected' : 'disconnected'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;chatConnected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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="s1"&gt;غير متصل&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- غرف المحادثة --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chat-rooms"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"room in chatRooms"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"room.id"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"room"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"joinRoom(room.id)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;room&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s2"&gt;`غرفة ${room.id&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;messages&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;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message in chatMessages&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&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;strong&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;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;senderName&lt;/span&gt; &lt;span class="si"&gt;}}&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;/strong&amp;gt; {{ message.body &lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&gt;إرسال&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;send-message&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;input&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;newMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&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="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;إرسال&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--&lt;/span&gt; &lt;span class="nx"&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;div&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notifications&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;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification in notifications&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;notification&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;h4&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;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h4&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="nx"&gt;p&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;notification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&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="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;markAsRead(notification.id)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;تمييز&lt;/span&gt; &lt;span class="nx"&gt;كمقروء&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&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="nx"&gt;span&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unread-count&lt;/span&gt;&lt;span class="dl"&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;unreadCount&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/span&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;/div&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;/div&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;/template&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="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&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="nx"&gt;useFirebaseExample&lt;/span&gt; &lt;span class="err"&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;@/composables/useFirebaseExample&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="nx"&gt;chatMessages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatRooms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;notifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;unreadCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;currentUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;chatConnected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initializeChat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;joinChatRoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sendChatMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;initializeNotifications&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;createNotification&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;markNotificationAsRead&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cleanupAll&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseExample&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;newMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&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;selectedRoomId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// تهيئة Firebase&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// تسجيل الدخول كضيف&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;signInAnonymously&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&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="nf"&gt;initializeChat&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;initializeNotifications&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// الانضمام لغرفة محادثة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;joinRoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;joinChatRoom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// إرسال رسالة&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sendMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sendChatMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectedRoomId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// مسح الرسالة&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;خطأ في إرسال الرسالة:&lt;/span&gt;&lt;span class="dl"&gt;'&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="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// تمييز إشعار كمقروء&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;markAsRead&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;markNotificationAsRead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notificationId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;خطأ في تمييز الإشعار كمقروء:&lt;/span&gt;&lt;span class="dl"&gt;'&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="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// تنظيف عند إغلاق المكون&lt;/span&gt;
&lt;span class="nf"&gt;onUnmounted&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="nf"&gt;cleanupAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;}&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;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🔧 التخصيص
&lt;/h2&gt;

&lt;h3&gt;
  
  
  اختيار نوع قاعدة البيانات
&lt;/h3&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;chatFirebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useRealtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// true للـ Realtime Database، false للـ Firestore&lt;/span&gt;
  &lt;span class="na"&gt;collectionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// يمكن تغييرها&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  تغيير أسماء المجموعات
&lt;/h3&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;notificationFirebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseNotifications&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;collectionName&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="c1"&gt;// يمكن تغييرها&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  إضافة معالجات الأحداث
&lt;/h3&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;chatFirebase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFirebaseChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;firebaseConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;onNewMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&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;// منطق مخصص عند استلام رسالة جديدة&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;رسالة جديدة:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// يمكن إضافة صوت أو إشعار هنا&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;onMessageError&lt;/span&gt;&lt;span class="p"&gt;:&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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&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;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;خطأ في الرسالة:&lt;/span&gt;&lt;span class="dl"&gt;'&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📋 الميزات
&lt;/h2&gt;

&lt;h3&gt;
  
  
  المحادثات
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ رسائل فورية&lt;/li&gt;
&lt;li&gt;✅ رسائل مؤقتة (Optimistic Updates)&lt;/li&gt;
&lt;li&gt;✅ إرسال ملفات&lt;/li&gt;
&lt;li&gt;✅ إدارة الغرف&lt;/li&gt;
&lt;li&gt;✅ إدارة الأخطاء&lt;/li&gt;
&lt;li&gt;✅ تنظيف الموارد&lt;/li&gt;
&lt;li&gt;✅ دعم Firestore و Realtime Database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  الإشعارات
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ إشعارات فورية&lt;/li&gt;
&lt;li&gt;✅ عداد الإشعارات غير المقروءة&lt;/li&gt;
&lt;li&gt;✅ تمييز الإشعارات كمقروءة&lt;/li&gt;
&lt;li&gt;✅ تصفية الإشعارات حسب النوع&lt;/li&gt;
&lt;li&gt;✅ إدارة الإشعارات&lt;/li&gt;
&lt;li&gt;✅ Push Notifications&lt;/li&gt;
&lt;li&gt;✅ دعم Firestore و Realtime Database&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  المصادقة
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ تسجيل دخول مجهول&lt;/li&gt;
&lt;li&gt;✅ تسجيل دخول بالبريد الإلكتروني&lt;/li&gt;
&lt;li&gt;✅ إدارة حالة المستخدم&lt;/li&gt;
&lt;li&gt;✅ تسجيل الخروج&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  عام
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ إدارة الاتصال&lt;/li&gt;
&lt;li&gt;✅ معالجة الأخطاء&lt;/li&gt;
&lt;li&gt;✅ تنظيف الذاكرة&lt;/li&gt;
&lt;li&gt;✅ قابلية التخصيص&lt;/li&gt;
&lt;li&gt;✅ TypeScript support&lt;/li&gt;
&lt;li&gt;✅ دعم جميع خدمات Firebase&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  📝 ملاحظات
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;تأكد من إعداد مشروع Firebase في Firebase Console&lt;/li&gt;
&lt;li&gt;تأكد من تفعيل الخدمات المطلوبة (Authentication, Firestore/Realtime Database, Messaging)&lt;/li&gt;
&lt;li&gt;استخدم قواعد الأمان المناسبة في Firestore/Realtime Database&lt;/li&gt;
&lt;li&gt;قم بتنظيف الموارد عند إغلاق المكونات&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🔥 خدمات Firebase المدعومة
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;تسجيل دخول مجهول&lt;/li&gt;
&lt;li&gt;تسجيل دخول بالبريد الإلكتروني&lt;/li&gt;
&lt;li&gt;إدارة حالة المستخدم&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Firestore
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;إضافة/تحديث/حذف المستندات&lt;/li&gt;
&lt;li&gt;الاشتراك في التغييرات&lt;/li&gt;
&lt;li&gt;الاستعلامات مع الفلاتر والترتيب&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Realtime Database
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;إضافة/تحديث/حذف البيانات&lt;/li&gt;
&lt;li&gt;الاشتراك في التغييرات&lt;/li&gt;
&lt;li&gt;إدارة المسارات&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud Messaging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Push Notifications&lt;/li&gt;
&lt;li&gt;إدارة الأذونات&lt;/li&gt;
&lt;li&gt;استقبال الرسائل&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/AhmedNiazy309/Firebase-Composables-" rel="noopener noreferrer"&gt;Download Firebase Composables&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Nuxt 4.2 — A Deep, Comprehensive Guide to Everything New</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Tue, 18 Nov 2025 10:03:34 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/nuxt-42-a-deep-comprehensive-guide-to-everything-new-fkb</link>
      <guid>https://dev.to/ahmed_niazy/nuxt-42-a-deep-comprehensive-guide-to-everything-new-fkb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lqm177irwuel9vyjt5b.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%2F2lqm177irwuel9vyjt5b.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
Nuxt 4.2 is one of those releases that quietly delivers huge improvements across the DX (developer experience), performance, debugging, and TypeScript productivity spectrum.&lt;br&gt;
It doesn’t introduce flashy breaking changes or conceptual complexity — instead, it refines the core parts of Nuxt that developers rely on every day.&lt;/p&gt;

&lt;p&gt;This article is a complete, long-form deep dive.&lt;br&gt;
By the end, you’ll fully understand every update in Nuxt 4.2, why it exists, and how to apply it with real examples and practical scenarios.&lt;/p&gt;

&lt;p&gt;Let’s dig in.&lt;/p&gt;


&lt;h2&gt;
  
  
  Nuxt 4.2 Introduces Abortable &lt;code&gt;useAsyncData&lt;/code&gt; — A Must-Have for Real Apps
&lt;/h2&gt;

&lt;p&gt;For years, developers asked for a way to &lt;strong&gt;cancel running data-fetch operations&lt;/strong&gt; when the user triggers a new action or navigates before the request completes.&lt;/p&gt;

&lt;p&gt;Nuxt 4.2 finally brings full support for &lt;strong&gt;AbortController&lt;/strong&gt; inside &lt;code&gt;useAsyncData()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;Imagine a search box where the user types fast, triggering multiple data loads.&lt;br&gt;
Without cancellation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You waste network requests&lt;/li&gt;
&lt;li&gt;You risk showing outdated results&lt;/li&gt;
&lt;li&gt;You create race conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you can &lt;strong&gt;abort the previous request&lt;/strong&gt; before starting a new one.&lt;/p&gt;
&lt;h3&gt;
  
  
  How It Works
&lt;/h3&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;controller&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;AbortController&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pending&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="nx"&gt;refresh&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAsyncData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;$fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/search?q=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;signal&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;signal&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// abort previous request when new input happens&lt;/span&gt;
&lt;span class="nf"&gt;watch&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="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;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nf"&gt;refresh&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  What Happens Internally?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When the request is aborted, Nuxt catches the abort error.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;pending&lt;/code&gt; state is cleared immediately.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useAsyncData&lt;/code&gt; does not update &lt;code&gt;data&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No race conditions occur.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  When to Use This
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Live search&lt;/li&gt;
&lt;li&gt;Infinite scroll&lt;/li&gt;
&lt;li&gt;Auto-refresh dashboards&lt;/li&gt;
&lt;li&gt;Form steps that change rapidly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is not only a DX improvement — it prevents bugs that actually happen in real production apps.&lt;/p&gt;


&lt;h2&gt;
  
  
  New: Better Error Pages in Development (A Perfect Blend of Your UI + Debug Info)
&lt;/h2&gt;

&lt;p&gt;This is one of the most underrated updates in all of Nuxt 4.x.&lt;/p&gt;

&lt;p&gt;Previously, if your app crashed during development, Nuxt showed a generic error overlay.&lt;br&gt;
If you created a custom error page (&lt;code&gt;error.vue&lt;/code&gt;), you couldn’t preview how it actually looked during runtime errors.&lt;/p&gt;

&lt;p&gt;Nuxt 4.2 changes this completely.&lt;/p&gt;
&lt;h3&gt;
  
  
  You Now Get TWO Things at the Same Time:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Your &lt;strong&gt;actual Nuxt error page&lt;/strong&gt; (the one your users see in production)&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Vite error overlay&lt;/strong&gt; with stack trace and debugging tools&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both appear simultaneously, layered intelligently.&lt;/p&gt;
&lt;h3&gt;
  
  
  Example Error Page (&lt;code&gt;error.vue&lt;/code&gt;)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"error-page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;NuxtLink&lt;/span&gt; &lt;span class="na"&gt;to=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Go Home&lt;span class="nt"&gt;&amp;lt;/NuxtLink&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Now in development:
&lt;/h3&gt;

&lt;p&gt;You see the real design &lt;strong&gt;plus&lt;/strong&gt; full debugging tools.&lt;br&gt;
You don’t need to choose one or hack the system anymore.&lt;/p&gt;
&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You can design UX for failures with full confidence.&lt;/li&gt;
&lt;li&gt;You debug faster.&lt;/li&gt;
&lt;li&gt;You no longer switch between two different error “worlds.”&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Vite Environment API — A Cleaner, More Predictable Env System
&lt;/h2&gt;

&lt;p&gt;Nuxt already offers &lt;code&gt;runtimeConfig&lt;/code&gt;, which is great for secure environment variables.&lt;/p&gt;

&lt;p&gt;But developers still want to use the familiar:&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuxt 4.2 now supports it experimentally via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;viteEnvironmentApi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;If you work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Third-party tools&lt;/li&gt;
&lt;li&gt;UI libraries&lt;/li&gt;
&lt;li&gt;Shared code across multiple projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You often need &lt;code&gt;import.meta.env&lt;/code&gt; to work exactly like Vite.&lt;/p&gt;

&lt;p&gt;Now it does.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&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;apiUrl&lt;/span&gt; &lt;span class="o"&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_API_URL&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to Prefer This
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When migrating Vite apps into Nuxt&lt;/li&gt;
&lt;li&gt;When you need identical behavior between SPA and SSR environments&lt;/li&gt;
&lt;li&gt;When integrating libraries relying heavily on &lt;code&gt;import.meta.env&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Huge Performance Wins: Async Data Handler Extraction
&lt;/h2&gt;

&lt;p&gt;This is a big one.&lt;br&gt;
Enabled via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extractAsyncDataHandlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What It Actually Does
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;useAsyncData()&lt;/code&gt; often contains server-only logic like:&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="nf"&gt;useAsyncData&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;$fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/products&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;p&gt;This logic &lt;strong&gt;should not&lt;/strong&gt; be inside the client bundle.&lt;br&gt;
But historically, it ended up there because Nuxt had to include it for hydration purposes.&lt;/p&gt;

&lt;p&gt;Nuxt 4.2 extracts this server-only logic so the browser &lt;strong&gt;never downloads it.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Real Impact
&lt;/h3&gt;

&lt;p&gt;Depending on how many &lt;code&gt;useAsyncData()&lt;/code&gt; calls your project has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundle size drops &lt;strong&gt;20%–40%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Faster hydration&lt;/li&gt;
&lt;li&gt;Faster first load&lt;/li&gt;
&lt;li&gt;Less JavaScript sent to the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a rare “enable and enjoy free performance” update.&lt;/p&gt;


&lt;h2&gt;
  
  
  TypeScript Plugin Support — This Is Next-Level DX
&lt;/h2&gt;

&lt;p&gt;This new feature is experimental and extremely powerful for large Nuxt codebases.&lt;/p&gt;

&lt;p&gt;Enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineNuxtConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;typescriptPlugin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What You Get
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Component Auto-Rename
&lt;/h4&gt;

&lt;p&gt;Rename a Vue file and all references update automatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Go To Definition for Runtime Utilities
&lt;/h4&gt;

&lt;p&gt;Jump into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useState()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useFetch()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Nuxt composables&lt;/li&gt;
&lt;li&gt;Config generated types&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Better IntelliSense Across the Entire Project
&lt;/h4&gt;

&lt;p&gt;Nuxt becomes easier to navigate, especially in mid–large codebases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario
&lt;/h3&gt;

&lt;p&gt;You rename:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;components/BaseButton.vue → components/Button.vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuxt TypeScript plugin updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;BaseButton/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Button/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;magically, everywhere.&lt;/p&gt;

&lt;p&gt;This is something developers have wanted for years.&lt;/p&gt;




&lt;h2&gt;
  
  
  Smaller Quality-of-Life Improvements
&lt;/h2&gt;

&lt;h3&gt;
  
  
  #1: &lt;code&gt;routeRules&lt;/code&gt; Now Keep the Hash
&lt;/h3&gt;

&lt;p&gt;Before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/products#top → /products
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No hash loss.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  #2: &lt;code&gt;&amp;lt;NuxtLink&amp;gt;&lt;/code&gt; Supports Object Href
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;NuxtLink&lt;/span&gt; &lt;span class="na"&gt;:href=&lt;/span&gt;&lt;span class="s"&gt;"{ name: 'product', params: { id: 12 } }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  View Product
&lt;span class="nt"&gt;&amp;lt;/NuxtLink&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  #3: Auto-Imported Components Work with &lt;code&gt;h()&lt;/code&gt;
&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;h&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;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nf"&gt;render&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;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyCard&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&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;No need for manual imports anymore.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Upgrade to Nuxt 4.2
&lt;/h2&gt;

&lt;p&gt;Just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx nuxt upgrade &lt;span class="nt"&gt;--dedupe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nuxt automatically updates dependencies and resolves duplicates.&lt;/p&gt;




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

&lt;p&gt;Nuxt 4.2 isn’t a huge feature release — it’s a &lt;strong&gt;developer happiness&lt;/strong&gt; release.&lt;/p&gt;

&lt;p&gt;It gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More control over async data&lt;/li&gt;
&lt;li&gt;Better debugging&lt;/li&gt;
&lt;li&gt;Faster loading&lt;/li&gt;
&lt;li&gt;Cleaner environment handling&lt;/li&gt;
&lt;li&gt;Significantly improved TypeScript support&lt;/li&gt;
&lt;li&gt;Smarter routing and linking behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And all of this without breaking anything.&lt;/p&gt;

&lt;p&gt;If you're building modern Vue applications, Nuxt 4.2 is one of the cleanest, smoothest upgrades you’ll ever apply.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>performance</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deep Dive into State Management in Vue 3: From Composition API to Pinia with Practical Insights</title>
      <dc:creator>Ahmed Niazy</dc:creator>
      <pubDate>Sun, 26 Oct 2025 06:55:51 +0000</pubDate>
      <link>https://dev.to/ahmed_niazy/deep-dive-into-state-management-in-vue-3-from-composition-api-to-pinia-with-practical-insights-h77</link>
      <guid>https://dev.to/ahmed_niazy/deep-dive-into-state-management-in-vue-3-from-composition-api-to-pinia-with-practical-insights-h77</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhlb0ynglk3ztr85eajd4.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%2Fhlb0ynglk3ztr85eajd4.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
When you build a Vue 3 app, you inevitably face this: &lt;em&gt;how should I manage the state?&lt;/em&gt; Do I just use the built-in features like &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;reactive&lt;/code&gt;, and composables via the Vue Composition API — or do I bring in a dedicated library like Pinia? This article will dive &lt;em&gt;deep&lt;/em&gt;, get &lt;em&gt;intense&lt;/em&gt;, pull apart the pros and cons, show you real code, ask you tough questions + give answers, and leave you with tasks. We’ll cover why it matters, when you might choose one over the other, and how you actually implement each.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why state management even matters, and why this decision is HUGE
&lt;/h2&gt;

&lt;p&gt;If your app is tiny – maybe one or two components – maybe state is trivial. But once you start growing: dozens of components, nested trees, modules, asynchronous fetches, caching, derived state, multiple teams working… the “state management” piece becomes &lt;em&gt;mission critical&lt;/em&gt;. Mess it up, and you’ll have bugs, spaghetti, unpredictable side-effects, data out of sync, re-render chaos, and maintenance nightmares.&lt;/p&gt;

&lt;p&gt;With Vue 3, you have this amazing power: the Composition API. It gives you flexibility, less ceremony, and the feeling of “just write plain JS”. On the flip side, you have Pinia, designed to be the “official” store library for Vue, offering structure, patterns, tooling, and ready-made store features.&lt;/p&gt;

&lt;p&gt;This decision – “do I just in-house build my store logic via composables or adopt Pinia?” – can shape how scalable your app is, how maintainable, how easy to onboard new developers, and how comfortable you’ll be when things go wrong. The stakes are high.&lt;/p&gt;


&lt;h2&gt;
  
  
  Using Composition API (no external store library) – what it looks like, its benefits &amp;amp; risks
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What it &lt;em&gt;looks like&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;With the Composition API approach, you lean on these built-in features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ref()&lt;/code&gt;, &lt;code&gt;reactive()&lt;/code&gt;, &lt;code&gt;computed()&lt;/code&gt;, &lt;code&gt;watch()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;You write your &lt;strong&gt;own&lt;/strong&gt; “store” modules as simple JS/TS modules or composables&lt;/li&gt;
&lt;li&gt;You might use &lt;code&gt;provide&lt;/code&gt;/&lt;code&gt;inject&lt;/code&gt; to share state across component trees&lt;/li&gt;
&lt;li&gt;You don’t add a dedicated store library (so fewer dependencies)&lt;/li&gt;
&lt;li&gt;Example:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/composables/useUsers.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;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onMounted&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;vue’
import type { Ref } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useUsers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&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="nl"&gt;loadUsers&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadUsers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&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;// pretend fetchUsers fetches User[]&lt;/span&gt;
    &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&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;fetchUsers&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;onMounted&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;void&lt;/span&gt; &lt;span class="nf"&gt;loadUsers&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="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadUsers&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;Then to distribute it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// injection-keys.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InjectionKey&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;vue’
import type { UsersHelper } from &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="nx"&gt;useUsers&lt;/span&gt;&lt;span class="err"&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;usersHelperKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InjectionKey&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UsersHelper&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;usersHelper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// ParentComponent.vue&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&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;ts&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;provide&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;vue’
import { useUsers } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/composables/u&lt;/span&gt;&lt;span class="nx"&gt;seUsers&lt;/span&gt;&lt;span class="err"&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;usersHelperKey&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;@/composables/injection-keys’

const usersHelper = useUsers()
provide(usersHelperKey, usersHelper)
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;ChildComponent /&amp;gt;
&amp;lt;/template&amp;gt;

// ChildComponent.vue
&amp;lt;script setup lang="ts"&amp;gt;
import { inject } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="err"&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;usersHelperKey&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;@/composables/injection-keys’

const usersHelper = inject(usersHelperKey)
&amp;lt;/script&amp;gt;
&amp;lt;template&amp;gt;
  &amp;lt;ul&amp;gt;
    &amp;lt;li v-for="u in usersHelper?.users" :key="u.id"&amp;gt;{{ u.name }}&amp;lt;/li&amp;gt;
  &amp;lt;/ul&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which shows: you &lt;em&gt;can&lt;/em&gt; build your own mini store using the Composition API + provide/inject.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No extra library to learn/install/configure → fewer dependencies.&lt;/li&gt;
&lt;li&gt;Very flexible: you tailor your “store” exactly how you want it.&lt;/li&gt;
&lt;li&gt;Lightweight: if your state needs are modest, this is ideal.&lt;/li&gt;
&lt;li&gt;Keeps parts of your app separated (you only share what you want).&lt;/li&gt;
&lt;li&gt;Great for small to medium projects, proof-of-concepts, or apps with limited state complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Risks / drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As your app grows, you’ll likely end up reinventing parts of what store libraries already solve: modules, namespacing, devtools support, persist, hot reload, debugging etc.&lt;/li&gt;
&lt;li&gt;Sharing global state or cross-tree state gets more manual (provide/inject or exporting singletons) – potential for mis-wiring or accidental coupling.&lt;/li&gt;
&lt;li&gt;Without clear structure, you can drift into chaos: many files, inconsistent patterns, multiple “useX” composables doing similar things but subtle differences.&lt;/li&gt;
&lt;li&gt;Harder to enforce patterns (especially across teams) or to debug/travel history of state changes.&lt;/li&gt;
&lt;li&gt;If you plan on many modules, many developers, large codebase – you’ll probably pay cost in maintainability.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Using Pinia – what it looks like, why it’s powerful, and when you’ll want it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What it &lt;em&gt;looks like&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Pinia gives you a structured store definition; it’s built for Vue 3, and integrates with devtools. 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="c1"&gt;// src/stores/counter.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;defineStore&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;pinia’

export const useCounterStore = defineStore(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, {
  state: () =&amp;gt; ({
    count: 0
  }),
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  },
  actions: {
    increment(amount = 1) {
      this.count += amount
    }
  }
})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in a component:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&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;ts&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;storeToRefs&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;pinia’
import { useCounterStore } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/stores/&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCounterStore&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;doubleCount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storeToRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;increment&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&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="nx"&gt;template&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;div&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;count&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;/p&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="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;doubleCount&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;/p&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="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handleClick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Increment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/div&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;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. The structure is obvious: you have &lt;code&gt;state&lt;/code&gt;, &lt;code&gt;getters&lt;/code&gt;, &lt;code&gt;actions&lt;/code&gt;. Pinia gives you all the things you expect from a store library, but with minimal boilerplate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it’s powerful
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Global registration: you can access your store from anywhere in the app easily.&lt;/li&gt;
&lt;li&gt;DevTools integration: you get time-travel, inspect state changes, debug flows more easily.&lt;/li&gt;
&lt;li&gt;Orderly structure: modules (stores) are well defined; no implicit “magic” leaks.&lt;/li&gt;
&lt;li&gt;TypeScript support is strong (Pinia was built with TS in mind) → fewer type headaches.&lt;/li&gt;
&lt;li&gt;Scaling is easier: when you add more features, more modules, more devs, the store architecture is solid.&lt;/li&gt;
&lt;li&gt;Community momentum: since many Vue 3 apps now adopt Pinia, you’ll find patterns, plugins, ecosystem support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When you’ll want it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;If you’re building a large or medium-sized app (many components, many modules, cross-domain state).&lt;/li&gt;
&lt;li&gt;If multiple developers will touch the state layer (you want consistency, predictability).&lt;/li&gt;
&lt;li&gt;If you care about debugging, state traceability, devtools, hot module replacement.&lt;/li&gt;
&lt;li&gt;If your state management is a non-trivial part of your app (carts, user sessions, persistent state, multiple modules, real-time events etc.).&lt;/li&gt;
&lt;li&gt;If you want fewer custom “home-rolled” solutions and prefer something you can rely on.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison – side by side
&lt;/h2&gt;

&lt;p&gt;Here’s a more &lt;strong&gt;extreme&lt;/strong&gt; breakdown of how they differ, when one shines, when one struggles.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Concern&lt;/th&gt;
&lt;th&gt;Composition API (no store library)&lt;/th&gt;
&lt;th&gt;Pinia&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Setup overhead&lt;/td&gt;
&lt;td&gt;Very low – just use composables + built-in APIs&lt;/td&gt;
&lt;td&gt;Low to medium – install Pinia, register plugin, then define stores&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning curve&lt;/td&gt;
&lt;td&gt;Familiar JS + Vue concepts; freedom to design your own&lt;/td&gt;
&lt;td&gt;Slight overhead to learn Pinia APIs, but straightforward&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency&lt;/td&gt;
&lt;td&gt;Zero external store library; minimal footprint&lt;/td&gt;
&lt;td&gt;One additional library (Pinia) added to your stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structure / Architecture&lt;/td&gt;
&lt;td&gt;Loose – you design modules, naming, boundaries yourself&lt;/td&gt;
&lt;td&gt;Defined – you create stores with state/getters/actions; architecture is more consistent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharing global state&lt;/td&gt;
&lt;td&gt;Manual sharing (export singletons or provide/inject)&lt;/td&gt;
&lt;td&gt;Built-in global shared store support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging / Dev tools&lt;/td&gt;
&lt;td&gt;More manual – you may need to create custom hooks/logging&lt;/td&gt;
&lt;td&gt;Rich dev tools, time-travel, plugins, clear store snapshots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript support&lt;/td&gt;
&lt;td&gt;Good but you may need more manual type definition or boilerplate&lt;/td&gt;
&lt;td&gt;Very good – Pinia supports TS out of the box nicely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling to large apps&lt;/td&gt;
&lt;td&gt;Requires discipline, good architecture; risk of fragmentation&lt;/td&gt;
&lt;td&gt;Built for scaling; modules, stores, team collaboration easier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility / freedom&lt;/td&gt;
&lt;td&gt;Maximum freedom – you decide everything&lt;/td&gt;
&lt;td&gt;Slightly less freedom (you follow Pinia’s pattern) but still very flexible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lightweight apps&lt;/td&gt;
&lt;td&gt;Ideal for small apps where adding a library feels heavy&lt;/td&gt;
&lt;td&gt;Works, but may feel like overkill for very tiny apps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team / maintainability&lt;/td&gt;
&lt;td&gt;Requires standards, conventions to avoid spaghetti&lt;/td&gt;
&lt;td&gt;Out-of-the-box conventions assist maintainability&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The verdict (with some &lt;em&gt;extreme emphasis&lt;/em&gt;)
&lt;/h3&gt;

&lt;p&gt;If you are working on a &lt;strong&gt;small&lt;/strong&gt; application or you know for sure that your state needs are modest, you might choose &lt;strong&gt;just the Composition API&lt;/strong&gt;. It’s lean, fast to set up, no extra dependencies, and you can keep things simple.&lt;/p&gt;

&lt;p&gt;But if you are building something &lt;strong&gt;non-trivial&lt;/strong&gt;, or expect growth, or expect more team members, or you want the comfort of structured state management, then &lt;strong&gt;Pinia&lt;/strong&gt; is the &lt;em&gt;much safer bet&lt;/em&gt;. The added structure, tooling, clarity will repay you hugely when things get complex.&lt;/p&gt;

&lt;p&gt;In fact: if I were building a “real world” app today, I would probably &lt;strong&gt;start with Pinia&lt;/strong&gt; unless I was absolutely sure the app will remain trivial. Because once you reach a certain size, switching later is more painful than starting with the right tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-world code examples + comparisons
&lt;/h2&gt;

&lt;p&gt;Here are &lt;strong&gt;two scenarios&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using Composition API only&lt;/li&gt;
&lt;li&gt;Same scenario using Pinia&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example Scenario: Shopping Cart
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Composition API version
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/composables/useCart.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;reactive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&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;vue’

interface CartItem {
  id: number
  name: string
  quantity: number
  price: number
}

const state = reactive({
  items: [] as CartItem[]
})

export function useCart() {
  const items = computed(() =&amp;gt; state.items)

  const totalQuantity = computed(() =&amp;gt; state.items.reduce((sum, i) =&amp;gt; sum + i.quantity, 0))
  const totalPrice = computed(() =&amp;gt; state.items.reduce((sum, i) =&amp;gt; sum + i.quantity * i.price, 0))

  function addItem(item: CartItem) {
    const existing = state.items.find(i =&amp;gt; i.id === item.id)
    if (existing) {
      existing.quantity += item.quantity
    } else {
      state.items.push(item)
    }
  }

  function removeItem(id: number) {
    const index = state.items.findIndex(i =&amp;gt; i.id === id)
    if (index !== -1) {
      state.items.splice(index, 1)
    }
  }

  return {
    items,
    totalQuantity,
    totalPrice,
    addItem,
    removeItem
  }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in your components you import &lt;code&gt;useCart()&lt;/code&gt; and everything is reactive. You don’t need to install anything extra.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: simple, direct.&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: if you add many modules (cart, user, products, orders), you’ll need to manage each module’s file, potentially manage injection or exports. Debugging becomes manual. You’ll need to enforce “who uses what state” and avoid cross-module entanglement.&lt;/p&gt;
&lt;h4&gt;
  
  
  Pinia version
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/stores/cart.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;defineStore&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;pinia’

interface CartItem {
  id: number
  name: string
  quantity: number
  price: number
}

export const useCartStore = defineStore(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, {
  state: () =&amp;gt; ({
    items: [] as CartItem[]
  }),
  getters: {
    totalQuantity: (state) =&amp;gt; state.items.reduce((sum, i) =&amp;gt; sum + i.quantity, 0),
    totalPrice: (state) =&amp;gt; state.items.reduce((sum, i) =&amp;gt; sum + i.quantity * i.price, 0)
  },
  actions: {
    addItem(item: CartItem) {
      const existing = this.items.find(i =&amp;gt; i.id === item.id)
      if (existing) {
        existing.quantity += item.quantity
      } else {
        this.items.push(item)
      }
    },
    removeItem(id: number) {
      const index = this.items.findIndex(i =&amp;gt; i.id === id)
      if (index !== -1) {
        this.items.splice(index, 1)
      }
    }
  }
})
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And in component:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;setup&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;ts&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;storeToRefs&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;pinia’
import { useCartStore } from &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="sr"&gt;/stores/&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCartStore&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;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalQuantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalPrice&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;storeToRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleAdd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;cart&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addItem&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&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;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&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="nx"&gt;template&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;div&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt; &lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;totalQuantity&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;/p&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="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Total&lt;/span&gt; &lt;span class="nx"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;totalPrice&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;/p&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="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handleAdd&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Add&lt;/span&gt; &lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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="nx"&gt;ul&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;li&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i in items&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;i.id&lt;/span&gt;&lt;span class="dl"&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;i&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="err"&gt;×&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&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;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cart.removeItem(i.id)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Remove&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;/li&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;/ul&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;/div&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;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;: structured, debugging tools, predictable, scalable.&lt;br&gt;
&lt;strong&gt;Cons&lt;/strong&gt;: slightly more setup, you must adopt Pinia’s style/patterns (which is fine for most). For trivial apps maybe it’s overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  Questions &amp;amp; Answers section
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1.&lt;/strong&gt; &lt;em&gt;Is it wrong to use the Composition API only for everything, never using Pinia?&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;A1.&lt;/strong&gt; Not at all wrong – for small or medium apps, Composition API alone is fully valid. But you must be disciplined: define modules, separate concerns, ensure you don’t end up with one giant “state bag” that everything reaches into. If you foresee growth, you’ll likely pay later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2.&lt;/strong&gt; &lt;em&gt;If I start with Composition API and later switch to Pinia, will it be hard?&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;A2.&lt;/strong&gt; It depends on how you structured things. If you kept things modular (each composable handles its own concerns) and you avoided ad-hoc state access everywhere, you’ll find migrating easier. If you have many components drilling state manually, you’ll probably need to refactor larger parts of your app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3.&lt;/strong&gt; &lt;em&gt;Does Pinia lock me in or reduce flexibility?&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;A3.&lt;/strong&gt; Not really. Pinia is quite flexible. You still write actions, getters, state. You can still use composables inside your stores. The pattern is clear but you retain freedom. The benefit is you get structure rather than rigid restriction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4.&lt;/strong&gt; &lt;em&gt;What about performance – is using Pinia slower?&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;A4.&lt;/strong&gt; In most cases, no significant difference. Pinia is lightweight and optimized for Vue 3. Unless you have extremely tight performance constraints, the overhead is negligible compared to the developer benefit of structure and tooling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q5.&lt;/strong&gt; &lt;em&gt;What factors should influence my choice between the two?&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;A5.&lt;/strong&gt; Factors to check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many modules / domains in your state (cart, user, products, etc.).&lt;/li&gt;
&lt;li&gt;Do you have multiple developers working on state?&lt;/li&gt;
&lt;li&gt;Do you need debugging tools / time-travel / devtools support?&lt;/li&gt;
&lt;li&gt;Will the state grow more complex (async, derived, caching, resets)?&lt;/li&gt;
&lt;li&gt;Is the application expected to scale significantly?&lt;/li&gt;
&lt;li&gt;How comfortable are you with building your own structure vs using a built-in one?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Tasks for you to try
&lt;/h2&gt;

&lt;p&gt;Here are some &lt;strong&gt;hands-on tasks&lt;/strong&gt; to &lt;em&gt;cement&lt;/em&gt; the knowledge. Try both approaches.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Task A (Composition API only):&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Create a simple blog app: posts + comments.&lt;/li&gt;
&lt;li&gt;Build a composable &lt;code&gt;usePosts()&lt;/code&gt; that loads posts from a mock API, tracks loading/error state, allows adding a post.&lt;/li&gt;
&lt;li&gt;Build &lt;code&gt;useComments(postId)&lt;/code&gt; that loads comments for a given post, allows adding/removing comments.&lt;/li&gt;
&lt;li&gt;Make sure you share state as needed between parent/child components (maybe via provide/inject) or a simple module export.&lt;/li&gt;
&lt;li&gt;Then measure: how easy is it to access posts + comments from arbitrary components? How easy to debug? What happens when state gets more complex (e.g., caching, concurrent loads)?&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Task B (Pinia version):&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Convert the blog app using Pinia. Create two stores: &lt;code&gt;postsStore&lt;/code&gt; and &lt;code&gt;commentsStore&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In each store, keep state, getters (e.g., commentsCount), and actions (e.g., fetchPosts, addPost, fetchComments, addComment).&lt;/li&gt;
&lt;li&gt;Use the stores in components. Use devtools to inspect state changes.&lt;/li&gt;
&lt;li&gt;Reflect: How did the architecture differ? Which one felt cleaner? Which one easier to maintain when you add more features (e.g., editing posts, filtering posts, reacting to user login)?&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Task C (Scaling scenario):&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Pretend your blog app is going to expand: you’ll add user authentication, user preferences, theme switching, notifications, offline caching, and multiple teams contributing.&lt;/li&gt;
&lt;li&gt;Map out (by hand or in a doc) how you would structure your state modules in each approach (Composition API only vs Pinia).&lt;/li&gt;
&lt;li&gt;Identify potential pain points in each. For example: in the Composition API version you might have many small composables, some of them overlapping responsibilities; in the Pinia version you might need to decide on store names, module splitting, but you already have clear patterns.&lt;/li&gt;
&lt;li&gt;Decide which approach you would adopt for this scaling scenario and write down your reasoning.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final thoughts (and a bit of hyperbole)
&lt;/h2&gt;

&lt;p&gt;Let’s be clear: Choosing between “Composition API alone” vs “Pinia” is &lt;em&gt;not just a small internal decision&lt;/em&gt;. It &lt;em&gt;can&lt;/em&gt; define how maintainable, scalable, and &lt;em&gt;pleasant&lt;/em&gt; your development experience will be. If you ignore structure now, you may pay for it later in chaotic merges, obscure bugs, duplicated logic, and developer frustration.&lt;/p&gt;

&lt;p&gt;On the other hand, if you skip over-engineering and keep it simple when it's simple, you’ll save time, keep things nimble, and avoid bloat. There’s a sweet spot.&lt;/p&gt;

&lt;p&gt;But please: &lt;strong&gt;don’t&lt;/strong&gt; assume one size fits all. It’s okay to start simple. It’s okay to evolve. What matters is that you &lt;strong&gt;choose intentionally&lt;/strong&gt;, not by default.&lt;/p&gt;

&lt;p&gt;If I were to issue a bold statement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"If you think your app will even remotely grow beyond trivial size, pick Pinia. If you’re absolutely sure it will stay tiny, the Composition API alone will serve."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And yes — if you pick Composition API now and later hit scaling constraints, migrating may cost more than deciding right up front. But it’s also true that starting with Pinia in a 2-page app might feel like using a sledgehammer to crack a nut.&lt;/p&gt;

&lt;p&gt;In the end: you want &lt;strong&gt;clarity&lt;/strong&gt;, &lt;strong&gt;predictability&lt;/strong&gt;, &lt;strong&gt;maintainability&lt;/strong&gt;, and &lt;strong&gt;developer happiness&lt;/strong&gt;. Choose the tool that supports that for &lt;em&gt;your context&lt;/em&gt;. Write your composables or build your stores, and keep your state management not just working — but &lt;em&gt;elegant&lt;/em&gt;.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>architecture</category>
      <category>javascript</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
