Project Description
Quiz AI is a Chrome extension that generates interactive quizzes from any webpage content using artificial intelligence.
The extension extracts content from the current webpage and uses Google's Gemini 1.5 Pro API to generate quizzes
based on user preferences (quiz type, difficulty, and number of questions).
Users can take the generated quizzes, check their answers, and review correct answers to test their understanding
of the webpage content.
Technology Stack
JavaScript
Chrome Extension API
HTML/CSS
Tailwind CSS
Google Gemini API
JSON
High-Level Architecture
graph TD
User[User] --- Browser[Chrome Browser]
Browser --- Extension[Quiz AI Extension]
Extension --- Popup[Popup Interface]
Extension --- ContentScript[Content Script]
Extension --- BackgroundService[Background Service]
ContentScript --- WebpageContent[Webpage Content]
Popup --- GeminiAPI[Google Gemini API]
subgraph "Extension Components"
PopupUI[Popup UI] --- QuizConfig[Quiz Configuration]
QuizConfig --- QuizGeneration[Quiz Generation]
QuizGeneration --- QuizDisplay[Quiz Display]
QuizDisplay --- Scoring[Scoring System]
end
subgraph "Content Script Components"
ContentExtraction[Content Extraction] --- ContentCleaning[Content Cleaning]
ContentCleaning --- ContentFormatting[Content Formatting]
end
Extension --- Extension_Components[Extension Components]
ContentScript --- Content_Script_Components[Content Script Components]
classDef browser fill:#d1e7dd,stroke:#20c997;
classDef extension fill:#cfe2ff,stroke:#0d6efd;
classDef content fill:#e2e3e5,stroke:#6c757d;
classDef api fill:#f8d7da,stroke:#dc3545;
class Browser browser;
class Extension extension;
class ContentScript content;
class GeminiAPI api;
Detailed Component Architecture
graph TD
subgraph "Popup"
PopupHTML["popup.html"] --> UIElements["UI Elements"]
UIElements --> QuizTypeSelect["Quiz Type Selection"]
UIElements --> DifficultySelect["Difficulty Selection"]
UIElements --> QuestionCountInput["Question Count Input"]
UIElements --> GenerateButton["Generate Button"]
UIElements --> LoadingIndicator["Loading Indicator"]
UIElements --> QuizContainer["Quiz Container"]
PopupJS["popup.js"] --> EventListeners["Event Listeners"]
EventListeners --> GenerateButtonClick["Generate Button Click"]
EventListeners --> FormSubmit["Form Submit"]
EventListeners --> ShowAnswersClick["Show Answers Click"]
PopupJS --> APIIntegration["API Integration"]
APIIntegration --> GenerateQuizFunc["generateQuiz() Function"]
APIIntegration --> ParseQuizFunc["parseQuizResponse() Function"]
PopupJS --> UIFunctions["UI Functions"]
UIFunctions --> DisplayQuizFunc["displayQuiz() Function"]
UIFunctions --> CheckAnswersFunc["checkAnswers() Function"]
UIFunctions --> DisplayAnswersFunc["displayAnswers() Function"]
end
subgraph "Content Script"
ContentJS["content.js"] --> MessageListener["Message Listener"]
MessageListener --> GetPageContentAction["getPageContent Action"]
ContentJS --> ExtractContentFunc["extractPageContent() Function"]
ExtractContentFunc --> ArticleExtraction["Article Extraction"]
ExtractContentFunc --> MainExtraction["Main Tag Extraction"]
ExtractContentFunc --> ContainerExtraction["Container Extraction"]
ExtractContentFunc --> BodyCloneExtraction["Body Clone Extraction"]
ExtractContentFunc --> ContentCleaning["Content Cleaning"]
end
subgraph "Background Service"
BackgroundJS["background.js"] --> InstallListener["Install Listener"]
BackgroundJS --> MessageListener2["Message Listener"]
MessageListener2 --> SaveQuizAction["saveQuiz Action"]
SaveQuizAction --> StorageAPI["Chrome Storage API"]
end
PopupJS -.-> ContentJS["Sends Messages"]
ContentJS -.-> PopupJS["Returns Content"]
PopupJS -.-> BackgroundJS["Sends Quiz Data"]
classDef popup fill:#f0f7ff,stroke:#3b82f6;
classDef content fill:#f0fdf4,stroke:#22c55e;
classDef background fill:#fef3c7,stroke:#d97706;
class Popup popup;
class Content_Script content;
class Background_Service background;
Project Structure
quiz-ai/
├── manifest.json # Extension configuration
├── popup.html # User interface
├── popup.js # Main functionality
├── content.js # Page content extraction
├── background.js # Background service worker
├── images/ # Extension icons
│ ├── icon16.png
│ ├── icon48.png
│ └── icon128.png
├── README.md # Documentation
└── LICENSE # MIT License
Data Flow Diagram
sequenceDiagram
participant User
participant Popup as Popup UI
participant Content as Content Script
participant API as Gemini API
participant Background as Background Service
User->>Popup: Click Extension Icon
Popup->>User: Display Quiz Configuration
User->>Popup: Set Quiz Parameters
User->>Popup: Click "Generate Quiz"
Popup->>Popup: Show Loading State
Popup->>Content: Request Page Content
Content->>Content: Extract Content
Content->>Popup: Return Page Content
Popup->>API: Send Content + Parameters
API->>Popup: Return Generated Quiz
Popup->>Popup: Parse Quiz Response
Popup->>Popup: Display Quiz
User->>Popup: Complete Quiz
User->>Popup: Submit Quiz
Popup->>Popup: Calculate Score
Popup->>Popup: Display Results
User->>Popup: Click "Show Answers"
Popup->>Popup: Display Correct Answers
User->>Popup: Save Quiz (Optional)
Popup->>Background: Send Quiz Data
Background->>Background: Store Quiz
Detailed API Integration
graph LR
subgraph "Chrome Extension API"
Tabs["chrome.tabs"] --- Query["query()"]
Tabs --- SendMessage["sendMessage()"]
Scripting["chrome.scripting"] --- ExecuteScript["executeScript()"]
Runtime["chrome.runtime"] --- OnMessage["onMessage"]
Runtime --- SendMessage2["sendMessage()"]
Storage["chrome.storage"] --- LocalSet["local.set()"]
Storage --- LocalGet["local.get()"]
end
subgraph "Gemini API"
GenerateContent["generateContent"] --- Prompt["Prompt Construction"]
GenerateContent --- Response["Response Parsing"]
GenerateContent --- Config["Generation Config"]
Config --- Temperature["temperature"]
Config --- MaxTokens["maxOutputTokens"]
Config --- SafetySettings["safetySettings"]
end
Query --- GetActiveTab["Get Active Tab"]
ExecuteScript --- InjectContentScript["Inject Content Script"]
SendMessage --- RequestContent["Request Page Content"]
OnMessage --- HandleMessages["Handle Messages"]
SendMessage2 --- SaveQuiz["Save Quiz"]
LocalSet --- StoreQuiz["Store Quiz Data"]
GenerateContent --- CreateQuiz["Create Quiz"]
Prompt --- ContentFormatting["Format Content"]
Response --- ParseJSON["Parse JSON Response"]
classDef chrome fill:#dbeafe,stroke:#3b82f6;
classDef gemini fill:#dcfce7,stroke:#22c55e;
class Chrome_Extension_API chrome;
class Gemini_API gemini;
Extension Activation Flow
graph LR
A["User Clicks Extension Icon"] --> B["Load popup.html"]
B --> C["Execute popup.js"]
C --> D["Add Event Listeners"]
D --> E["Wait for User Input"]
E --> F["User Configures Quiz"]
F --> G["User Clicks Generate"]
G --> H["Get Current Tab"]
H --> I["Inject Content Script"]
I --> J["Request Page Content"]
J --> K["Process Content"]
K --> L["Call Gemini API"]
L --> M["Display Quiz"]
style A fill:#d4f4e2,stroke:#34d399,stroke-width:3px,color:#065f46,font-weight:bold
style B fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style C fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style D fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style E fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style F fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style G fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style H fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style I fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style J fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style K fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style L fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style M fill:#d4f4e2,stroke:#34d399,stroke-width:3px,color:#065f46,font-weight:bold
User Flow
graph LR
A["Start"] --> B["Browse a Webpage"]
B --> C["Click Quiz AI Icon"]
C --> D["Select Quiz Type"]
D --> E["Choose Difficulty"]
E --> F["Set Question Count"]
F --> G["Click Generate Quiz"]
G --> H["Wait for Generation"]
H --> I["Take Quiz"]
I --> J["Submit Answers"]
J --> K["View Score"]
K --> L["Review Correct Answers"]
style A fill:#d4f4e2,stroke:#34d399,stroke-width:3px,color:#065f46,font-weight:bold
style B fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style C fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style D fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style E fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style F fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style G fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style H fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style I fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style J fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
style K fill:#fecaca,stroke:#ef4444,stroke-width:3px,color:#7f1d1d,font-weight:bold
style L fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e40af
Content Extraction Implementation
graph TD
subgraph "Content Extraction Process"
Start[Start Extraction] --> CheckArticle[Check for Article Tag]
CheckArticle --> ArticleExists{Article Exists?}
ArticleExists -->|Yes| ExtractArticle[Extract Article Text]
ArticleExists -->|No| CheckMain[Check for Main Tag]
CheckMain --> MainExists{Main Exists?}
MainExists -->|Yes| ExtractMain[Extract Main Text]
MainExists -->|No| CheckContainers[Check Common Containers]
CheckContainers --> ContainerExists{Container Exists?}
ContainerExists -->|Yes| ExtractContainer[Extract Container Text]
ContainerExists -->|No| CloneBody[Clone Body Element]
CloneBody --> RemoveNonContent[Remove Non-Content Elements]
RemoveNonContent --> ExtractBodyText[Extract Body Text]
ExtractArticle --> CleanContent[Clean Content]
ExtractMain --> CleanContent
ExtractContainer --> CleanContent
ExtractBodyText --> CleanContent
CleanContent --> TrimWhitespace[Trim Whitespace]
TrimWhitespace --> NormalizeSpaces[Normalize Spaces]
NormalizeSpaces --> LimitLength[Limit Content Length]
LimitLength --> ReturnContent[Return Content]
end
classDef process fill:#f0f7ff,stroke:#3b82f6;
class Content_Extraction_Process process;
Quiz Generation Process
sequenceDiagram
participant Popup as Popup.js
participant API as Gemini API
participant Parser as Response Parser
participant Display as Quiz Display
Popup->>Popup: Call generateQuiz()
Popup->>Popup: Prepare API URL and Key
Popup->>Popup: Construct Prompt
Note over Popup: Include content, quiz type, difficulty, and question count
Popup->>API: Send API Request
API->>API: Process Content
API->>API: Generate Quiz Questions
API->>Popup: Return JSON Response
Popup->>Parser: Parse Response
Parser->>Parser: Extract JSON
Parser->>Parser: Validate Structure
Parser->>Popup: Return Structured Quiz
Popup->>Display: Call displayQuiz()
Display->>Display: Generate HTML
Display->>Display: Add Event Listeners
Display->>Popup: Show Quiz UI
Quiz Display Implementation
graph TD
DisplayQuiz["displayQuiz() Function"] --> GenerateHTML["Generate Quiz HTML"]
GenerateHTML --> CreateForm["Create Quiz Form"]
CreateForm --> AddQuestions["Add Questions"]
AddQuestions --> AddOptions["Add Answer Options"]
AddOptions --> AddButtons["Add Submit/Show Answers Buttons"]
AddButtons --> AttachListeners["Attach Event Listeners"]
AttachListeners --> FormSubmit["Form Submit Listener"]
AttachListeners --> ShowAnswersClick["Show Answers Button Listener"]
FormSubmit --> CheckAnswers["checkAnswers() Function"]
CheckAnswers --> CalculateScore["Calculate Score"]
CheckAnswers --> DisplayScore["Display Score"]
ShowAnswersClick --> DisplayAnswers["displayAnswers() Function"]
DisplayAnswers --> ShowCorrectAnswers["Show Correct Answers"]
DisplayAnswers --> HighlightOptions["Highlight Options"]
classDef display fill:#f0f7ff,stroke:#3b82f6
class DisplayQuiz,GenerateHTML,CreateForm,AddQuestions,AddOptions,AddButtons,AttachListeners,FormSubmit,ShowAnswersClick,CheckAnswers,CalculateScore,DisplayScore,DisplayAnswers,ShowCorrectAnswers,HighlightOptions display
Message Passing Architecture
sequenceDiagram
participant Popup as Popup (popup.js)
participant Content as Content Script (content.js)
participant Background as Background Service (background.js)
Note over Popup,Background: Chrome Extension Message Passing
Popup->>Content: chrome.tabs.sendMessage({action: "getPageContent"})
Content->>Content: Extract page content
Content->>Popup: sendResponse({content, success: true})
Popup->>Background: chrome.runtime.sendMessage({action: "saveQuiz", quiz: quizData})
Background->>Background: Store quiz in chrome.storage.local
Background->>Popup: sendResponse({success: true})
State Management Flow
graph TD
subgraph "Extension State"
ExtensionState[Extension State] --> UIState[UI State]
ExtensionState --> QuizState[Quiz State]
ExtensionState --> StorageState[Storage State]
UIState --> LoadingState[Loading State]
UIState --> QuizDisplayState[Quiz Display State]
UIState --> ErrorState[Error State]
QuizState --> QuizConfig[Quiz Configuration]
QuizState --> QuizQuestions[Quiz Questions]
QuizState --> UserAnswers[User Answers]
QuizState --> QuizResults[Quiz Results]
StorageState --> SavedQuizzes[Saved Quizzes]
end
classDef state fill:#f0f7ff,stroke:#3b82f6;
class Extension_State state;
Quiz Response Format
graph TD
subgraph "Quiz JSON Format"
QuizJSON[Quiz JSON Array] --> Question1[Question 1]
QuizJSON --> Question2[Question 2]
QuizJSON --> QuestionN[Question N]
Question1 --> Q1Text[question]
Question1 --> Q1Options[options]
Question1 --> Q1Answer[correct_answer]
Q1Options --> Option1[Option 1]
Q1Options --> Option2[Option 2]
Q1Options --> Option3[Option 3]
Q1Options --> Option4[Option 4]
end
classDef json fill:#f0f7ff,stroke:#3b82f6;
class Quiz_JSON_Format json;
Development Workflow
sequenceDiagram
participant Developer
participant Git as Git Repository
participant Chrome as Chrome Browser
participant Extension as Extension Manager
Developer->>Git: Clone Repository
Developer->>Developer: Edit Source Files
Developer->>Chrome: Open chrome://extensions
Developer->>Extension: Enable Developer Mode
Developer->>Extension: Load Unpacked Extension
Chrome->>Developer: Test Extension
Developer->>Developer: Make Changes
Developer->>Chrome: Reload Extension
Developer->>Git: Commit Changes
Future Enhancements
graph TD
subgraph "Planned Features"
Export[Export Functionality] --> ExportPDF[Export to PDF]
Export --> ExportCSV[Export to CSV]
Templates[Quiz Templates] --> SubjectTemplates[Subject-Specific Templates]
Templates --> CustomTemplates[Custom Templates]
Templates --> SavedTemplates[Saved Templates]
History[Quiz History] --> SavedQuizzes[Saved Quizzes]
History --> QuizStats[Quiz Statistics]
History --> ProgressTracking[Progress Tracking]
Integration[Additional Integrations] --> LMSIntegration[LMS Integration]
Integration --> SocialSharing[Social Sharing]
Integration --> AIImprovements[Enhanced AI Models]
end
classDef future fill:#f0f7ff,stroke:#3b82f6;
class Planned_Features future;
Getting Started
To run the extension locally:
- Clone the repository
git clone https://github.com/imfeniljikadara/quiz-ai.git
- Configure the API key:
- Load the extension in Chrome:
- Open Chrome and navigate to
chrome://extensions/
- Enable "Developer mode" in the top right
- Click "Load unpacked" and select the extension directory
- Use the extension:
- Click the Quiz AI icon while on any webpage
- Select your quiz preferences
- Click "Generate Quiz"
- Take the quiz and check your understanding!
Conclusion
Quiz AI is a powerful Chrome extension that leverages artificial intelligence to generate interactive quizzes from any webpage content.
With its intuitive interface and seamless integration with Google's Gemini API, Quiz AI makes it easy to test your understanding of any online material.
The extension's architecture utilizes Chrome's Extension API and modern web technologies to provide a smooth quiz generation and taking experience,
while its modular design makes it easy to extend with new features in the future.