Auto-Coursera — AI-powered Coursera quiz assistant
Architecture Overview
A technical guide to how Auto-Coursera works under the hood. For contributors and the curious.
System Diagram
Content Script Layer
The content script runs on every Coursera page and is responsible for detecting, extracting, and applying answers.
Question Detection
A MutationObserver watches for quiz elements matching specific
selectors:
div[data-testid^="part-Submission_"]— submission containersdiv[role="group"][aria-labelledby*="-legend"]— question groups
Detection is debounced at 300ms to avoid reacting to intermediate DOM states during Coursera's React rendering.
Content Extraction
Once a question is detected, the extraction pipeline pulls:
- Question text — the main question body
- Images — via the CORS image pipeline (see below)
- LaTeX — mathematical notation in questions
- Code blocks — programming questions
- Answer options — radio buttons, checkboxes, or text inputs
Answer Application
Applying answers to Coursera's React-controlled inputs requires a 3-strategy click cascade:
- React synthetic events — dispatch React-compatible change events
- Native DOM clicks — fallback to standard
click() - Direct input manipulation — set
.valueand dispatchinput/changeevents for text fields
The cascade tries each strategy in order until the answer is confirmed as applied.
Service Worker Layer
The Manifest V3 service worker is the central coordinator. It never touches
the DOM directly — all communication happens via
chrome.runtime.sendMessage.
Message Routing
Every message between content scripts (and between tabs) passes through the service worker's message router. Messages are typed and validated.
AI Provider Manager
Manages all 5 providers with a circuit breaker pattern:
- Closed — provider is healthy, requests go through
- Open — provider has failed too many times, requests are routed to the next provider
- Half-open — after a cooldown, one test request is sent to check if the provider has recovered
Providers are tried in the order set by the user's priority configuration.
Rate Limiter
A token bucket rate limiter prevents exceeding provider rate limits. Each provider has its own bucket with configurable capacity and refill rate.
Batch Processor
Questions are collected and sent in batches with an 800ms debounce. This avoids sending one API call per question — instead, the entire quiz (or newly detected questions) are batched into a single request.
Prompt Engine
Constructs structured prompts from extracted question data. The prompt format varies by provider and question type (multiple choice vs. code expression vs. image-based).
CORS Image Pipeline
Coursera images are subject to CORS restrictions. The service worker fetches images via its own context (which is not subject to page-level CORS), converts them to base64, and returns them to the content script for inclusion in AI prompts.
Widget Layer
The entire UI is rendered inside a Shadow DOM, completely isolating it from Coursera's page styles and DOM.
Floating Action Button (FAB)
The FAB is a draggable button with 5 visual states:
| State | Appearance |
|---|---|
| Disabled | Greyed out — extension is off or no quiz detected |
| Idle | Default — ready to scan |
| Processing | Animated — waiting for AI response |
| Active | Answers have been applied |
| Error | Something went wrong — click for details |
Control Panel
A 320×480px panel that slides out from the FAB. Contains the results view, per-question confidence display, and action buttons.
Settings Overlay
Full-screen overlay with a focus trap for accessibility. Contains provider configuration, key management, and behavior settings.
WidgetStore
A reactive state store built on EventTarget-based pub/sub.
Components subscribe to state changes and re-render automatically — no
framework needed.
ContentBridge
Handles bidirectional communication between the widget (inside Shadow DOM) and the content script (in the page context). Uses custom events for decoupled messaging.
Cross-Cutting Concerns
Question Deduplication
Each question is fingerprinted using FNV-1a hashing to prevent re-processing the same question if the page re-renders or the user navigates back.
API Key Encryption
All API keys are encrypted at rest using AES-256-GCM with a key derived via PBKDF2 (100,000 iterations). Keys are decrypted only when needed for an API call and never stored in plaintext. This protects against casual inspection of raw browser storage data, but is not a defense against malicious extensions with storage access or full browser-profile compromise.
Structured Logging
Internal logs use a structured format with automatic key sanitization — API keys and tokens are redacted before any log output.
Tab-Scoped State
All runtime state is scoped per-tab with automatic recovery. If a tab crashes or the service worker restarts, state is reconstructed from persisted checkpoints.
Auto-Update
The extension checks version.json every 6 hours
for new releases. Users are notified of available updates through the
extension panel.
AI Providers
See the Setup Guide for configuration instructions.
| Provider | Key Format | Best For |
|---|---|---|
| OpenRouter | sk-or-... | General use — many free models, automatic routing |
| Gemini | AIza... | Generous free tier, strong reasoning |
| Groq | gsk_... | Ultra-fast inference, low latency |
| Cerebras | cbs-... | Fast inference, good free tier |
| NVIDIA NIM | nvapi-... | Vision models for image-based questions |
Circuit Breaker Failover
When a provider fails (timeout, rate limit, server error), the circuit breaker opens and traffic is routed to the next provider in priority order. After a cooldown period, the breaker enters a half-open state and sends a single test request. If it succeeds, the provider is restored; if it fails, the cooldown resets.
This means you should always configure at least two providers for uninterrupted service.
Contributing
Auto-Coursera is open source and contributions are welcome. Whether it's fixing bugs, improving documentation, or suggesting features — every contribution helps.