iPlusFlow
Track solved problems, visualize daily streaks, organize universal notes, compare friends' accepted submissions, and synchronize your competitive programming workflow directly inside Codeforces.
See how iPlusFlow seamlessly integrates into the Codeforces layout without tab context switching.
Chrome Extension Architecture
High-performance Chrome Extension for competitive programming with Shadow DOM isolation, asynchronous scraping, and synchronized cloud storage.
- User opens a problem:
workspace_widget.tsxmounts globally across all Codeforces URLs.content.tsxactivates exclusively on/problemset/problem/*. - Background validates cache:
content.tsxattaches a closedShadowRootand mounts the problem workspace sealed against host stylesheet rules. - Shadow DOM mounts workspace: The React workspace queries solved status and friends
data, triggering
background.tsto verify local cache validity before querying REST APIs. - Scraper executes in parallel: Up to 20 friends' submission pages are fetched
concurrently using a 700ms adaptive sliding window and
DOMParser. - React updates storage & UI: Submission IDs and notes commit to
chrome.storage.sync(`100KB` managed quota) and local cache, updating streak badges across tabs instantly.
| Component File | Architectural Responsibilities |
|---|---|
| Popup.tsx |
|
| background.ts |
|
| workspace_widget.tsx |
|
| content.tsx |
|
| friendsCode.ts |
|
Why Dual Content Scripts over a Single Monolithic Content Script?
- Performance & Footprint: Injecting syntax highlighters and scrapers on general
pages would bloat memory. By isolating
content.tsxexclusively to `/problem/*` URLs, general pages run only the ultra-lightweight floating button (workspace_widget.tsx). - Separation of Concerns: The floating widget runs cleanly in global document context, whereas the problem workspace enforces strict `Shadow DOM` encapsulation against complex host tables.
Why Centralized Types & Decoupled Hooks over Colocated Interfaces & God Components?
- Centralized Type Definition Layer (
types/index.ts): Consolidated all component prop contracts (`FriendsSidebarProps`, `CodeModalProps`, `StreakInfo`) into a single contract hub, eliminating duplicate inline declarations and preventing circular dependencies. - Decoupled Solved Status & Streak Sync (
useSolvedStatus.ts): Extracted over 60 lines of complex business logic from `ProblemWorkspace.tsx` into a dedicated hook managing storage caching, API polling, and streak recalculations independently of rendering. - Decoupled Friends Data Pipeline (
useFriendsData.ts): Extracted friends cache synchronization and `fetchFriendsList()` scraping fallbacks from sidebar components, keeping UI components purely focused on layout.
Every engineering outcome below is rigorously verified against actual repository code. Expand Evidence βΌ to inspect exact source paths, implementation mechanisms, and architectural rationale.
Evidence βΌ
Evidence βΌ
Evidence βΌ
Evidence βΌ
Evidence βΌ
Evidence βΌ
Evidence βΌ
Evidence βΌ
Shadow DOM Isolation & React Portals Simulator
Injecting rich interactive UI components directly into native Codeforces tables without CSS bleed.
Click the buttons below to simulate how content.tsx mounts a protective
Shadow Root (#iplus-problem-root) and teleports React Portals into live
Codeforces DOM targets!
domHelpers.ts)WHY Shadow DOM? (The CSS Bleed Problem):
Codeforces uses legacy global CSS rules like div { font-family: Arial }
and global table styles. If an extension injects normal React components into the page, Codeforces styles
distort extension buttons, while extension CSS leaks into Codeforces page elements. Creating a Shadow Root
(host.attachShadow({ mode: 'open' })) provides a 100% protective style
forcefield in both directions.
WHY React Portals? (Container Locator Pattern):
Instead of scattering raw document.createElement calls, findCodeforcesContainers() queries native targets (.problem-statement .title, #sidebar). ReactDOM.createPortal projects specific UI components into these targets
while keeping React state centralized in the Shadow DOM root. Calling removeCodeforcesContainers() on unmount cleans up wrapper nodes to prevent
memory leaks.
Low-Level Design (LLD) Breakdown:
- Container Locator Pattern:
findCodeforcesContainers()locates 7 native injection targets (.problem-statement .title,#sidebar,.second-level-menu-list) and creates wrapper containers. - React Portals Setup:
createPortal(<ProblemWorkspace />, targetNode)mounts UI trees inside Shadow DOM without polluting host DOM. - Clean Lifecycle Tear-down:
removeCodeforcesContainers()removes all injected wrapper elements on React unmount to ensure zero memory leaks.
Friends' Solutions Scraper Simulator
Asynchronous parallel HTML extraction, DOMParser pipeline, and syntax highlighting preview.
friendsCode.ts)WHY a Scraper is Required:
The official Codeforces JSON API returns submission metadata (verdict, time, memory), but never returns raw user source code strings! To enable peer learning where users study friends' solutions directly on the problem page, we must fetch and parse the submission HTML.
HOW the Scraper Pipeline Works:
- Friend Handles: Fetches
https://codeforces.com/friendsin background to parse active friend handles. - Status Lookup: Queries
contest.status(fast) or falls back touser.statusto identify submissions with verdictOK. - 700ms Throttle: Enforces
rateLimitedFetch()with a minimum700msdelay between API requests to prevent HTTP 429 rate limit bans. - DOMParser Extraction: Parses raw HTML using
new DOMParser().parseFromString()and extracts<pre class="prettyprint">safely without executing external scripts.
Low-Level Design (LLD) Breakdown:
- Rate Limited Fetch: Throttles API fetches with a minimum
700mswindow between requests. - Two-Tier API Fallback Strategy: Queries
contest.statusfirst (scoped fast lookup), falling back touser.statusif contest endpoints return empty. - DOMParser Extraction & Prettify: Uses browser-native
DOMParserto extract<pre class="prettyprint">code blocks securely without script execution risks.
Real Extension Default Popup & Floating Orb Simulator
Click the floating orb icon below to launch the 1:1 exact copy of the real extension default popup window
(MainUI, ProblemTable, NotesModal).
FloatingWorkspace.tsx & filterHelpers.ts)
WHY Architectural Dual Realm (Popup vs Content Script)?
The Extension Popup (App.tsx, MainUI.tsx) runs in Chrome toolbar context and dies completely from RAM when
closed. The Content Script (workspace_widget.tsx) lives persistently
inside codeforces.com/* pages. Both realms decouple data using chrome.storage.
WHY Derived State for Table Filters (filterHelpers.ts)?
Instead of maintaining redundant filtered arrays that easily fall out of sync, problemsToShow is derived on the fly right before render (filterProblems & sortProblems). React
recalculates this derived calculation whenever inputs or headers change, guaranteeing 100% data accuracy
with zero state-sync bugs.
Low-Level Design (LLD) Breakdown:
- 3-Slot Vertical Snapping Math:
getSlotY(slot)calculates target Y coordinates (top: 20px,middle: containerHeight / 2,bottom: containerHeight - 70px). - Click vs Drag Threshold: Mouse movements <
5pxreleased within250mstoggle popup visibility, whereas drags compute proximity tominDiff(diffTop, diffMid, diffBot). - Stable Table Sorting:
sortProblems()usesoriginalIndexas a tie-breaker during multi-column sort operations to maintain deterministic row ordering.
Gamified 2-Week Daily Streaks Simulator
Click on calendar days below across 2 full weeks (14 days) to toggle problem solves and recalculate live
streak totals using the exact streak.ts algorithm.
β
β
β
β
β
β
β
β
β
β
β
β
β
β
streak.ts)WHY Daily Streaks?
Gamifies competitive programming by rewarding continuous practice habits. Converts raw submission
timestamps into a clean local Set<string> of YYYY-MM-DD dates.
HOW Streak Algorithm Operates:
- Current Streak Continuation: Checks if
dateSetincludestodayoryesterday. If yes, a date cursor decrements day-by-day to count active streak length. - Record Streak Scan: Sorts date strings ascending and runs a linear scan to find
maximum consecutive day sequences (
diffDays === 1). - 15-Minute Local Caching: Results are cached in
chrome.storage.localunderstreak_handlewith a 15-minute TTL to minimize Codeforces API traffic.
Low-Level Design (LLD) Breakdown:
- DateSet Linear Scan: Converts submission timestamps to local
YYYY-MM-DDstrings stored in aSet<string>. - Current Streak Continuation Rule: Checks if
dateSetcontainstodayoryesterday. If yes, decrements a date cursor day-by-day to count active streak length. - Longest Streak Scan: Sorts date array ascending and computes consecutive day deltas
(
diffDays === 1) to track all-time record streak.
Chrome Storage Schema & Inspector
Inspect JSON structures committed to chrome.storage.sync and chrome.storage.local.
Click above to inspect storage payload...
storage.ts)WHY Storage Tiering?
Chrome extension popup React states are destroyed when the popup closes. We tier storage based on data size and sync frequency:
chrome.storage.sync(100KB Limit, 8KB/Key): Used for user bookmarks, handle, and custom notes so they sync across all Chrome browsers automatically.chrome.storage.local(5MB+ Limit): Used for heavy cached payloads (friends list, raw code snippets, streak history, orb Y-slot).chrome.storage.onChanged: Listens to storage mutation events to synchronize state in real time across all open Codeforces tabs without page reloads.
Low-Level Design (LLD) Breakdown:
- Sync Storage (
chrome.storage.sync): 100KB quota total, 8KB per key. Used forcf_handle,bookmarks, anduser_notes. - Local Storage (
chrome.storage.local): 5MB limit. Used for heavy API payload caches (cached_friends,streak_info, orb coordinates). - Storage Observer: Listens to
chrome.storage.onChangedevents for instant cross-tab state updates without page reloads.
SDE Architecture & SRE Reliability Technical Book
Click any card below to launch an interactive technical deep-dive popup dialog with full implementation details, LLD/HLD patterns, and engineering Q&A.