Thanks to visit codestin.com
Credit goes to github.com

Skip to content

JitishxD/TUFdsa

Repository files navigation

πŸš€ TUFDsa - DSA Practice Companion

TUFDsa Logo

Your Personal DSA Practice Tracker & Problem Recommendation Engine

Chrome Extension Manifest V3 React Vite TailwindCSS License: MIT


πŸ“‹ Table of Contents


🌟 Overview

TUFDsa is a feature-rich Chrome Extension designed for developers and students who want to systematically improve their Data Structures and Algorithms (DSA) skills.

The Problem It Solves

  • 🎯 Decision Fatigue: No more wondering "which problem should I solve today?"
  • πŸ“Š Scattered Progress: Track all your solved problems across multiple platforms in one place
  • πŸ”₯ Motivation Loss: Streak system keeps you accountable with daily practice goals
  • 🧠 Context Switching: Get AI-powered hints without leaving your coding environment

Who Is This For?

  • πŸ’Ό Job Seekers preparing for technical interviews
  • πŸŽ“ Students learning DSA fundamentals
  • πŸ‘¨β€πŸ’» Developers wanting to stay sharp with daily practice
  • πŸ† Competitive Programmers tracking their progress

✨ Key Features

Feature Description
🎲 Random Problem Generator Get a random problem based on difficulty, topics, or company tags
πŸ“š A2Z DSA Sheet Integration Follow the popular TakeUForward A2Z DSA course systematically
πŸ”₯ Streak System Calendar-based streak tracking with "at-risk" warnings
πŸ” Multi-Platform Search Search problems from LeetCode, GeeksforGeeks, and Code360
πŸ€– AI Assistant Ask AI for hints, complexity analysis, and explanations
πŸŒ™ New Tab Override Replace Chrome's new tab with your DSA dashboard
⚑ Quick Access Open problems with id for quick access across 3000+ problem from LeetCode, GeeksforGeeks, and Code360
🎚️ Advanced Filters Filter by difficulty, topics, company, and solved status
😈 Torture Mode Hardcore mode that disables skipping problems
πŸ“Š Statistics Dashboard Track total solved, daily progress, and streak history

πŸ“Έ Screenshots

New Tab Dashboard

New Tab Dashboard

Popup Interface

Popup Interface

AI Assistant

AI Assistant

Options Page

Options Page


πŸ› οΈ Tech Stack

Core Technologies

Technology Version Purpose
React 18.2.x UI Components & State Management
Vite 7.x Build Tool & Dev Server
@crxjs/vite-plugin 2.0.0-beta Chrome Extension Integration
Tailwind CSS 4.x Utility-First Styling

Key Dependencies

Package Purpose
react-markdown Render AI responses with Markdown formatting
axios HTTP client (used in scrapers)
puppeteer Web scraping for problem data updates

Development Tools

Tool Purpose
prettier Code formatting
gulp + gulp-zip Extension packaging
glob File pattern matching

πŸ—οΈ High Level Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                            CHROME BROWSER                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚                       TUFdsa EXTENSION                               β”‚   β”‚
β”‚   β”‚                                                                      β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚   β”‚  β”‚   POPUP     β”‚  β”‚   NEWTAB    β”‚  β”‚   OPTIONS   β”‚  β”‚ SIDEPANEL  β”‚   β”‚   β”‚
β”‚   β”‚  β”‚   popup/    β”‚  β”‚   newtab/   β”‚  β”‚   options/  β”‚  β”‚ sidepanel/ β”‚   β”‚   β”‚
β”‚   β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚            β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”  β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ React β”‚  β”‚  β”‚  β”‚ React β”‚  β”‚  β”‚  β”‚ React β”‚  β”‚  β”‚ β”‚ React β”‚  β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β”‚  App  β”‚  β”‚  β”‚  β”‚  App  β”‚  β”‚  β”‚  β”‚  App  β”‚  β”‚  β”‚ β”‚  App  β”‚  β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β””β”€β”€β”€β”¬β”€β”€β”€β”˜  β”‚  β”‚  β””β”€β”€β”€β”¬β”€β”€β”€β”˜  β”‚  β”‚  β””β”€β”€β”€β”¬β”€β”€β”€β”˜  β”‚  β”‚ β””β”€β”€β”€β”¬β”€β”€β”€β”˜  β”‚   β”‚   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚   β”‚         β”‚                β”‚                β”‚               β”‚          β”‚   β”‚
β”‚   β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚   β”‚
β”‚   β”‚                                 β”‚                                    β”‚   β”‚
β”‚   β”‚                                 β–Ό                                    β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚   β”‚
β”‚   β”‚  β”‚                    CHROME STORAGE API                           β”‚ β”‚   β”‚
β”‚   β”‚  β”‚                                                                 β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚   sync storage   β”‚        β”‚        local storage         β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚                  β”‚        β”‚                              β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β€’ solveHistory   β”‚        β”‚ β€’ (currently unused)         β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β€’ userSettings   β”‚        β”‚                              β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β€’ currentProblem β”‚        β”‚                              β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β”‚ β€’ savedFilters   β”‚        β”‚                              β”‚   β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚ β”‚   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚   β”‚
β”‚   β”‚                          β”‚                                           β”‚   β”‚
β”‚   β”‚                          β”‚ chrome.storage.onChanged                  β”‚   β”‚
β”‚   β”‚                          β–Ό                                           β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚   β”‚
β”‚   β”‚  β”‚                 SERVICE WORKER (background/)                    β”‚ β”‚   β”‚
β”‚   β”‚  β”‚                                                                 β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β€’ chrome.runtime.onMessage listener                            β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β€’ Event-driven lifecycle                                       β”‚ β”‚   β”‚
β”‚   β”‚  β”‚  β€’ Minimal code (offloads to UI contexts)                       β”‚ β”‚   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚   β”‚
β”‚   β”‚                                                                      β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                              β”‚
β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚   β”‚                         WEB PAGE CONTEXT                             β”‚   β”‚
β”‚   β”‚                                                                      β”‚   β”‚
β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚   β”‚
β”‚   β”‚  β”‚                     CONTENT SCRIPTS                           β”‚   β”‚   β”‚
β”‚   β”‚  β”‚                                                               β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  contentScript/index.js      contentScript/askAiHelper.js     β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β€’ Runs on all HTTP(S)       β€’ Runs on LeetCode/GFG/Code360   β”‚   β”‚   β”‚
β”‚   β”‚  β”‚  β€’ Generic injection         β€’ Extracts user code             β”‚   β”‚   β”‚
β”‚   β”‚  β”‚                                (With custom userscript)       β”‚   β”‚   β”‚
β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚   β”‚
β”‚   β”‚                                                                      β”‚   β”‚
β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                                                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Data Entities

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                       DATA ENTITIES                              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  SOLVE HISTORY (Source of Truth)                         β”‚    β”‚
β”‚  β”‚                                                          β”‚    β”‚
β”‚  β”‚  {                                                       β”‚    β”‚
β”‚  β”‚    "randomSolveHistory": {                               β”‚    β”‚
β”‚  β”‚      "[problemId]": 1704067200000  // timestamp          β”‚    β”‚
β”‚  β”‚    },                                                    β”‚    β”‚
β”‚  β”‚    "a2zSolveHistory": {                                  β”‚    β”‚
β”‚  β”‚      "[problemId]": 1704153600000                        β”‚    β”‚
β”‚  β”‚    }                                                     β”‚    β”‚
β”‚  β”‚  }                                                       β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  USER SETTINGS                                           β”‚    β”‚
β”‚  β”‚                                                          β”‚    β”‚
β”‚  β”‚  {                                                       β”‚    β”‚
β”‚  β”‚    darkMode: true,                                       β”‚    β”‚
β”‚  β”‚    tortureMode: false,                                   β”‚    β”‚
β”‚  β”‚    hyperTortureMode: false,                              β”‚    β”‚
β”‚  β”‚    dailyGoal: 1,                                         β”‚    β”‚
β”‚  β”‚    showDifficulty: true,                                 β”‚    β”‚
β”‚  β”‚    showTopics: true,                                     β”‚    β”‚
β”‚  β”‚    ...                                                   β”‚    β”‚
β”‚  β”‚  }                                                       β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                  β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  CURRENT PROBLEM STATE                                   β”‚    β”‚
β”‚  β”‚                                                          β”‚    β”‚
β”‚  β”‚  {                                                       β”‚    β”‚
β”‚  β”‚    "currentRandomProblem": { ...problemObject },         β”‚    β”‚
β”‚  β”‚    "lastA2zIndex": 42,                                   β”‚    β”‚
β”‚  β”‚    "randomProblemDataSource": "leetcode" | "gfg" | ...   β”‚    β”‚
β”‚  β”‚  }                                                       β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Component Breakdown

Component File Purpose
Popup src/popup/popup.html Quick access toolbar popup
New Tab src/newtab/newtab.html Dashboard replacing Chrome's new tab
Options src/options/options.html Settings and data management
Side Panel src/sidepanel/sidepanel.html Chrome side panel integration
DevTools src/devtools/devtools.html Developer tools panel
Service Worker src/background/index.js Dummy not used now
Content Scripts src/contentScript/ DOM interaction on coding platforms

Message Passing Flow

User clicks "Ask AI" with code
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    chrome.tabs.sendMessage      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Popup/UI      β”‚ ─────────────────────────────▢  β”‚ Content Script  β”‚
β”‚                 β”‚                                 β”‚                 β”‚
β”‚                 β”‚ ◀─────────────────────────────  β”‚ Extracts code   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    { type: "USER_CODE", ... }   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
   Sends to Cohere API
         β”‚
         β–Ό
   Displays AI Response

πŸš€ Installation & Setup / Build

Prerequisites

  • Node.js >= 20.19.0
  • npm or yarn
  • Google Chrome (latest recommended)

1. Clone the Repository

git clone https://github.com/JitishxD/TUFDsa.git
cd TUFDsa

2. Install Dependencies

npm install
# or
yarn install

3. Development Mode

Start the development server with hot reload:

npm run dev
# or
yarn dev
  1. Vite starts dev server
  2. CRXJS plugin watches for changes
  3. Extension auto-reloads in Chrome

4. Load Unpacked Extension in Chrome

  1. Open Chrome and navigate to chrome://extensions/
  2. Enable Developer mode (toggle in top-right)
  3. Click Load unpacked
  4. Select the build/ folder from this project

Note: During development, the extension will auto-reload when you make changes. You may need to refresh the extension or reload pages for content script changes.

5. Production Build

npm run build
# or
yarn build
  1. Vite builds optimized bundles
  2. CRXJS generates final manifest.json
  3. Assets are hashed for caching
  4. Output goes to an optimized production build in the build/ directory.

6. Package for Distribution

npm run zip
  1. Runs production build
  2. Gulp zips the build/ folder
  3. Creates TUFDsa-{version}.zip in package/

πŸ“ Folder Structure

TUFDsa/
β”œβ”€β”€ πŸ“„ package.json           # Dependencies and scripts
β”œβ”€β”€ πŸ“„ vite.config.js         # Vite + CRXJS configuration
β”œβ”€β”€ πŸ“„ vitest.config.js       # Vitest config file
β”œβ”€β”€ πŸ“„ jsconfig.json          # TypeScript/JS configuration
β”‚
β”œβ”€β”€ πŸ“‚ src/                   # Source code
β”‚   β”œβ”€β”€ πŸ“„ manifest.js        # Dynamic manifest generation
β”‚   β”œβ”€β”€ πŸ“„ zip.js             # Gulp-based packaging script
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ background/        # Service worker
β”‚   β”‚   └── πŸ“„ index.js       # Message listeners, events
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ contentScript/     # Content scripts
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.js       # Generic content script
β”‚   β”‚   └── πŸ“„ askAiHelper.js # Code extraction for AI
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ popup/             # Popup UI
β”‚   β”‚   β”œβ”€β”€ πŸ“„ popup.html     # HTML entry point (manifest: src/popup/popup.html)
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.jsx      # Entry point
β”‚   β”‚   β”œβ”€β”€ πŸ“„ PopUpHome.jsx  # Main popup component
β”‚   β”‚   β”œβ”€β”€ πŸ“„ aiIntegration.js # Cohere AI integration
β”‚   β”‚   β”œβ”€β”€ πŸ“‚ Components/    # Popup components
β”‚   β”‚   └── πŸ“‚ Styles/        # Popup styles
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ newtab/            # New Tab UI
β”‚   β”‚   β”œβ”€β”€ πŸ“„ newtab.html    # HTML entry point (manifest: src/newtab/newtab.html)
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.jsx      # Entry point
β”‚   β”‚   β”œβ”€β”€ πŸ“„ NewTab.jsx     # Dashboard component
β”‚   β”‚   β”œβ”€β”€ πŸ“‚ Components/    # Dashboard components
β”‚   β”‚   └── πŸ“‚ Styles/        # Dashboard styles
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ options/           # Options Page
β”‚   β”‚   β”œβ”€β”€ πŸ“„ options.html   # HTML entry point (manifest: src/options/options.html)
β”‚   β”‚   β”œβ”€β”€ πŸ“„ index.jsx      # Entry point
β”‚   β”‚   β”œβ”€β”€ πŸ“„ Options.jsx    # Settings component
β”‚   β”‚   β”œβ”€β”€ πŸ“‚ Components/    # Options components
β”‚   β”‚   └── πŸ“‚ Styles/        # Options styles
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ sidepanel/         # Chrome Side Panel
β”‚   β”‚   β”œβ”€β”€ πŸ“„ sidepanel.html # HTML entry point (manifest: src/sidepanel/sidepanel.html)
β”‚   β”‚   └── πŸ“„ SidePanel.jsx  # Side panel component
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ devtools/          # Chrome DevTools Panel
β”‚   β”‚   β”œβ”€β”€ πŸ“„ devtools.html  # HTML entry point (manifest: src/devtools/devtools.html)
β”‚   β”‚   └── πŸ“„ DevTools.jsx   # DevTools component
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ problem-data/      # Problem datasets (JSON)
β”‚   β”‚   β”œβ”€β”€ πŸ“„ DSAa2zProblems.json
β”‚   β”‚   β”œβ”€β”€ πŸ“„ leetCodeAllProblemDump.json
β”‚   β”‚   β”œβ”€β”€ πŸ“„ gfg_problems.json
β”‚   β”‚   └── πŸ“„ code360_problems_indexed.json
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“‚ utils/             # Shared utilities
β”‚   β”‚   β”œβ”€β”€ πŸ“„ statsTracker.js    # Streak & stats logic
β”‚   β”‚   β”œβ”€β”€ πŸ“„ problemFilters.js  # Filter utilities
β”‚   β”‚   β”œβ”€β”€ πŸ“„ useRandomProblem.js # Shared hook
β”‚   β”‚   └── πŸ“„ uiHelpers.js       # UI utilities
β”‚   β”‚
β”‚   └── πŸ“‚ assets/            # Static assets
β”‚
β”œβ”€β”€ πŸ“‚ public/                # Public assets
β”‚   β”œβ”€β”€ πŸ“‚ icons/             # Extension icons
β”‚   └── πŸ“‚ img/               # Images (logo, etc.)
β”‚
└── πŸ“‚ Scrapper/              # Problem data scrapers
    β”œβ”€β”€ πŸ“‚ leetCodeScrape/    # LeetCode scraping
    β”œβ”€β”€ πŸ“‚ geeksforgeeks/     # GFG scraping
    β”œβ”€β”€ πŸ“‚ code360/           # Code360 scraping
    └── πŸ“‚ TUFScrape/         # TakeUForward scraping

πŸ“œ NPM / Yarn Scripts

Script Command Description
dev npm run dev Start Vite dev server with HMR
build npm run build Production build to build/
preview npm run preview Preview production build
fmt npm run fmt Format code with Prettier
zip npm run zip Build + create distributable ZIP

πŸ” Environment Variables

The extension currently doesn't require environment variables for basic functionality.

Optional Configuration

Variable Purpose Where Used
API Keys Stored in Chrome Storage Options page / AI feature

Note: For security, API keys (like Cohere API key for AI features) are stored in Chrome's sync storage rather than environment variables.


❓ Common Issues / FAQ

πŸ”΄ Extension Not Loading

Problem: "Load unpacked" shows errors

Solution:

  1. Ensure you ran npm run build first
  2. Select the build/ folder, not the project root
  3. Check for manifest syntax errors

πŸ”΄ Hot Reload Not Working

Problem: Changes don't reflect in the extension

Solution:

  1. For popup/newtab: Close and reopen the popup/tab
  2. For content scripts: Refresh the target page
  3. For background: Reload the extension from chrome://extensions/

πŸ”΄ Content Script Not Injecting

Problem: "Could not reach content script" error

Solution:

  1. Refresh the target page after loading the extension
  2. Check if the URL matches patterns in manifest.js
  3. Verify permissions in manifest

πŸ”΄ AI Feature Not Working

Problem: "Permission denied" or API errors

Solution:

  1. Grant the https://api.cohere.ai/* permission when prompted
  2. Verify your API key is correct
  3. Check network connectivity

πŸ”΄ Storage Quota Exceeded

Problem: Solve history not saving

Solution:

  1. Clear old data from Options page
  2. Use the "Data Management" tab to export/backup
  3. Consider resetting progress if history is too large

πŸ”΄ CORS Errors

Problem: API requests blocked

Solution:

  • Ensure origin permissions are in manifest
  • Use background script for cross-origin requests

🀝 Contributing

We welcome contributions! Here's how to get started:

Branching Strategy

Branch Purpose
main Production-ready code
develop Integration branch
feature/* New features
fix/* Bug fixes
docs/* Documentation updates

Testing

The tests are in src/utils/streakCalculator.test.js and imports the implementation from statsTracker.js.

npm run test

Commit Conventions

Follow Conventional Commits:

feat: add new filter option for company tags
fix: resolve streak calculation bug
docs: update README with new screenshots
refactor: simplify useRandomProblem hook

Code Style

  • Formatting: Run npm run fmt before committing
  • Components: Use functional components with hooks
  • Naming:
    • Components: PascalCase
    • Utilities: camelCase
    • CSS classes: Use Tailwind utilities

Pull Request Process

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run npm run fmt
  5. Submit a PR with a clear description

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.


πŸ™ Acknowledgements


Made with ❀️ for the DSA community

Report Bug Β· Request Feature

About

A chrome extension to track progress of dsa problems

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published