diff --git a/apps/docs/content/(hash-table)/3-longest-substring-without-repeating-characters.mdx b/apps/docs/content/(hash-table)/3-longest-substring-without-repeating-characters.mdx
new file mode 100644
index 0000000..b0f4f83
--- /dev/null
+++ b/apps/docs/content/(hash-table)/3-longest-substring-without-repeating-characters.mdx
@@ -0,0 +1,47 @@
+---
+title: '3. Longest Substring Without Repeating Characters'
+description: Given a string s, find the length of the longest substring without duplicate characters
+sidebar:
+ label: 'Longest Substring Without Repeating Characters'
+ badge: 'Medium'
+---
+
+Sliding Window
+
+### Example 1:
+- Input: `s = "abcabcbb"`
+- Output: `3`
+- Explanation: The answer is "abc", with the length of `3`. Note that "bca" and "cab" are also correct answers.
+
+### Example 2:
+- Input: `s = "bbbbb"`
+- Output: `1`
+- Explanation: The answer is "b", with the length of `1`.
+
+### Example 3:
+- Input: `s = "pwwkew"`
+- Output: `3`
+- Explanation: The answer is "wke", with the length of `3`. Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
+
+### Constraints:
+
+- `0 <= s.length <= 10^5`
+- `s` consists of English letters, digits, symbols and spaces.
+
+## Solution
+
+```py
+class Solution:
+ def lengthOfLongestSubstring(self, s: str) -> int:
+ left = 0
+ ans = 0
+ seen = set()
+ for right, c in enumerate(s):
+ while c in seen:
+ seen.remove(s[left])
+ left += 1
+ seen.add(c)
+ ans = max(ans, right - left + 1)
+
+ return ans
+```
diff --git a/apps/docs/content/reference/sliding-window.mdx b/apps/docs/content/reference/sliding-window.mdx
new file mode 100644
index 0000000..8b6285d
--- /dev/null
+++ b/apps/docs/content/reference/sliding-window.mdx
@@ -0,0 +1,103 @@
+---
+title: Sliding Window
+description: 'Sliding window is a specialized two-pointer family where the pointers define a contiguous interval and you maintain information about that entire interval as it moves.'
+---
+
+:::warning
+This is the family where invariants matter the most
+:::
+
+## What Makes Sliding Window Different?
+
+Many problems have two moving boundaries. That alone does not make them sliding window problems.
+
+A problem belongs to this family when:
+
+- the answer depends on the subarray or substring between left and right
+- you can update the window state incrementally as elements enter or leave
+- you maintain a condition that tells you whether the window is valid
+
+## What is an Invariant?
+
+
+An invariant is a statement that stays true before and after every iteration.
+
+For sliding window, the invariant often looks like one of these:
+
+- "the current window is valid"
+- "the current window contains no duplicates"
+- "the current window sum is at most the target"
+- "the frequency map matches the characters currently inside the window"
+
+The invariant gives the loop its structure:
+
+- expand the window by moving right
+- update the window state
+- if the invariant breaks, shrink from the left until it holds again
+- update the answer only when you know the invariant is satisfied
+
+
+## Why Invariants Matter
+
+Without an invariant, shrinking the window becomes arbitrary. You no longer know:
+
+- when the window is valid
+- when to update the answer
+- why the left pointer should stop moving
+- The invariant is the reason the algorithm is correct.
+
+## The Main Subtypes
+
+### 1. Fixed-size windows
+
+:::tip
+The window size never changes. The main task is updating the window state efficiently when one element enters and one leaves.
+:::
+
+
+
+### 2. Flexible-size windows with a validity rule
+
+:::tip
+Here the window expands until invalid, then shrinks until valid again.
+:::
+
+
+
+
+### 3. Frequency-tracking windows
+
+:::tip
+The difficulty comes from keeping the bookkeeping correct as characters enter and leave.
+:::
+
+
+
+## How Sliding Window Differs From Other Two-Pointer Families
+
+Compare it with Container With Most Water:
+
+- In sliding window, the interval itself has meaning.
+- In container, the interval is just the remaining search space.
+
+Compare it with Remove Duplicates:
+
+- In sliding window, both pointers describe a live window.
+- In compaction, the left part of the array is already the answer prefix.
+
+## A Practical Template
+
+A common variable-size sliding window has this shape:
+
+1. Add the new rightmost element.
+2. Update the window state.
+3. While the invariant is broken, remove elements from the left.
+4. Once the invariant is restored, update the answer.
+
+The exact data structure changes from problem to problem, but the logic stays the same.
+
+As you work through this section, keep asking:
+
+:::warning
+What invariant does my window maintain, and at what moment is it safe to update the answer?
+:::
diff --git a/apps/docs/public/sliding-window-fixed-size.svg b/apps/docs/public/sliding-window-fixed-size.svg
new file mode 100644
index 0000000..b497628
--- /dev/null
+++ b/apps/docs/public/sliding-window-fixed-size.svg
@@ -0,0 +1,66 @@
+
diff --git a/apps/docs/public/sliding-window-flexible.svg b/apps/docs/public/sliding-window-flexible.svg
new file mode 100644
index 0000000..048b407
--- /dev/null
+++ b/apps/docs/public/sliding-window-flexible.svg
@@ -0,0 +1,66 @@
+
diff --git a/apps/docs/public/sliding-window-frequency.svg b/apps/docs/public/sliding-window-frequency.svg
new file mode 100644
index 0000000..0e8d5cf
--- /dev/null
+++ b/apps/docs/public/sliding-window-frequency.svg
@@ -0,0 +1,54 @@
+