Downloading files from Google Classroom shouldn't feel like a chore. CQD transforms bulk file downloads into a single click while powering an enterprise-grade analytics pipeline that tracks millions of download events at the edge.
📦 Get the Extension · 📖 Documentation · 📝 Changelog · 🏗️ Architecture · 🔒 Privacy
As a software engineer, I found myself trapped in a loop of repetitive, manual labor every time I needed course materials. Downloading files one-by-one wasn't just slow—it felt like a technical debt I was paying every day. Eventually, the "misery" of clicking through dozens of links became too much to ignore.
The plan for CQD didn't start in an IDE; it started on a piece of paper during a particularly boring university lecture. Out of pure frustration, I began sketching a solution. What started as a student's bored scribbles quickly evolved into a rigorous system architecture, complete with data flow diagrams and a security-first mindset.
I moved the plan from paper to Notion, created this repository, and began tracking the technical journey through GitHub issues.
- V1: A raw prototype built with native JavaScript.
- Modern Stack: After several iterations, I migrated to the WXT framework to build a robust, production-grade extension.
To ensure I wasn't alone in this frustration, I conducted a local survey among my colleagues. The results were unanimous: everyone was struggling. This "misery" reaches its peak during final exams, when we all rush to download massive amounts of study material, and every second wasted on manual clicks counts.
I've spent countless hours testing this extension across multiple browsers and operating systems to ensure every student has access to the "cure." Whether you are on Windows, Mac, or Linux, or using Chrome, Edge, or Firefox—I've got you covered.
(Wait, What about Safari? We don't talk about Safari. You're on your own there, buddy.)
CQD is built by a student, for students. It's a tool rooted in human connection and shared academic trauma, designed to make your student life just a little bit more bearable.
Getting CQD is quick and easy! Just install it from your browser's extension store.
| Browser | Install Link | How to Install |
|---|---|---|
| Chrome | Chrome Web Store | Click → Add to Chrome → Add Extension |
| Firefox | Firefox Add-ons | Click → Add to Firefox → Add |
| Edge | Edge Add-ons | Click → Get → Add Extension |
- You'll see the CQD icon appear in your browser toolbar 🎉
- Go to Google Classroom
- Open any assignment with attachments
- Click the download button and watch the magic happen!
👨💻 Want to run it locally for development? Check out the Developer Guide.
This is a complex distributed system. Each module has its own comprehensive README with implementation details, API references, and configuration guides. Start here for the big picture, then dive into the module you're working on.
| Module | Description | Documentation |
|---|---|---|
| 🧩 Extension | Browser extension for bulk downloading from Google Classroom. Built with WXT + React. | Read Extension Docs → |
| ⚡ Worker | Edge ingestion layer on Cloudflare. Buffers events in Durable Objects and pre-aggregates data. | Read Worker Docs → |
| 🏛️ Backend | Go server with SQLite storage, analytics API, and Google Sheets archiver. | Read Backend Docs → |
| 🛠️ Tools | DevOps scripts for validation, pipeline testing, and deployment automation. | View Scripts → |
CQD is not just a browser extension—it's a distributed analytics system designed for scale, resilience, and cost-efficiency.
graph TD
User((👤 Student)) -->|Clicks Download| Ext[🧩 Chrome Extension]
subgraph Client Side
Ext -->|Batch Logic| DL[Download Queue]
Ext -->|Anon Stats| Reporter[Analytics Reporter]
end
subgraph Edge Layer
Reporter -->|POST /track| CF[⚡ Cloudflare Worker]
CF -->|Buffer & Aggregation| DO[📦 Durable Object]
end
subgraph "Oracle Cloud Backend"
DO -->|Flush Batch| GoServer[🚀 Go Backend]
GoServer -->|Write| DB[(🗄️ SQLite DB)]
Cron[⏱️ Daily Cron] -->|Trigger| Archiver[📜 Archiver Tool]
end
subgraph External
Archiver -->|Append Row| Sheet[📊 Google Sheets]
end
┌─────────────────────────────────────────────────────────────────────────────────────────┐
│ USER'S BROWSER │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │ CQD Browser Extension (Client) │ │
│ │ • Bulk file downloads from Google Classroom │ │
│ │ • Automatic Drive confirmation bypass │ │
│ │ • Anonymous event tracking (file type, duration, success/fail) │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ POST /track (batched events) │
│ │ │
└──────────────────────────────────────────┼──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ CLOUDFLARE EDGE (Global) │
│ │
│ ┌────────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Worker + Durable Object │ │
│ │ • Low-latency ingestion at 300+ edge locations │ │
│ │ • Event buffering with Durable Object state persistence │ │
│ │ • Pre-aggregation: calculates Top Browser, Top Country, etc. │ │
│ │ • Smart batching with exponential backoff retry │ │
│ └────────────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ POST /ingest-batch (aggregated JSON) │
│ │ │
└──────────────────────────────────────────┼───────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ ORACLE CLOUD (ARM64 Ampere) │
│ │
│ ┌────────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Go Backend + SQLite (WAL Mode) │ │
│ │ • Persistent storage with zero external dependencies │ │
│ │ • Real-time analytics dashboard │ │
│ │ • Time-series data with hourly/daily granularity │ │
│ └────────────────────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Daily Cron Job │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Google Sheets (Archive) │ │
│ │ • Long-term historical data │ │
│ │ • Easy sharing and reporting │ │
│ └────────────────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────────────────┘
Every download attempt in the Extension triggers an analytics event. Here's its complete journey through the system:
- 📥 Capture (Client) — The Extension records: file type, browser, OS, duration, and success/fail status. Events are queued locally in
chrome.storage. - 📤 Batch & Send (Client → Edge) — When the queue reaches 50 events (or after a time threshold), the extension POSTs the batch to the Cloudflare Worker.
- 🔄 Buffer & Aggregate (Edge) — The Worker forwards events to its Durable Object, which:
- Persists events in memory (survives Worker restarts).
- Aggregates counters: by browser, by OS, by country, by file type.
- Calculates "Top" stats: most common browser, most active country, etc.
- Tracks delivery-stage counters (
accepted → stored → forwarded → committed) for end-to-end verification. - Rolls up structured failures (stage, code, detail, samples) for durable debugging.
- Manages security state: IP allowlists and login rate limits.
- 🚀 Flush (Edge → Backend) — When the buffer exceeds
MAX_BATCH_EVENTSor an alarm fires, the DO sends a pre-aggregated JSON payload to the Oracle Backend. - 💾 Store (Backend) — The Backend receives the batch, deduplicates by
batchId, and stores:
- Raw batch metadata in
batchestable. - Hourly aggregates in
downloads_hourlytable. - Lifetime totals in
downloads_totalskey-value table. - Delivery chain metrics in
pipeline_stage_dailyandpipeline_delivery_events. - Structured failure sink logs in
pipeline_failure_logswith retention cleanup.
- 📊 Archive (Backend → Sheets) — At midnight UTC, a cron job runs the Archiver, which:
- Fetches the current summary from the local API.
- Appends a row to Google Sheets with all dimension breakdowns.
CQD employs a defense-in-depth strategy to protect analytics integrity and admin interfaces.
- HttpOnly Cookies: Session tokens are stored in
HttpOnly,Secure,SameSite=Strictcookies, preventing XSS access. - HMAC-SHA256 Signatures: Tokens are signed with a high-entropy secret, preventing tampering.
- Short-Lived Sessions: Sessions expire automatically to minimize exposure.
- IP Allowlisting: Critical administrative actions are restricted to a dynamic list of allowed IPs, managed via the Durable Object state.
- Rate Limiting: Login attempts are rate-limited at the edge to prevent brute-force attacks.
- Admin Proxy Pattern: The browser never sees the
DO_SHARED_SECRET. The Cloudflare Worker validates the user's session and "injects" the secret into requests before forwarding them to the Durable Object.
Problem: If every extension sends events directly to our database, we'd have thousands of concurrent writes—overwhelming SQLite and spiking costs.
Solution: Durable Objects act as a global buffer. All events for a given namespace (e.g., "downloads") are routed to the same instance, regardless of which edge location receives the request. This provides:
- Strong consistency — No split-brain, no race conditions.
- Persistence — State survives Worker restarts.
- Rate limiting — We control how often we flush to the backend.
- Pre-aggregation — Compute "Top Browser" before sending, saving backend CPU.
Problem: We need maximum performance on Oracle Cloud's Free Tier (4 ARM cores, 24GB RAM) without paying for managed databases.
Solution: Go with pure-Go SQLite (no CGO) gives us:
- Single binary deployment — No runtime dependencies.
- Zero external services — No Postgres, no Redis, no connection pooling.
- WAL mode — Concurrent reads while writing.
- ARM64 optimized — Native compilation for Ampere A1.
Problem: Building Manifest v3 extensions with React is painful—bundling, HMR, multi-target builds.
Solution: WXT provides:
- File-system routing —
popup/index.html,background.ts,*.content.tsjust work. - Hot Module Replacement — See changes instantly during development.
- Cross-browser builds — Chrome and Firefox from the same codebase.
- TypeScript-first — Auto-imports, type safety, and modern DX.
| Layer | Language | Key Technologies | Data Flow |
|---|---|---|---|
| 🧩 Client | TypeScript | WXT, React 19, Chrome APIs | Captures events → Queues locally → Batches to Edge |
| ⚡ Edge | TypeScript | Cloudflare Workers, Durable Objects | Buffers events → Aggregates → Flushes to Backend |
| 🏛️ Backend | Go | net/http, SQLite (pure Go), Docker | Stores batches → Serves API → Archives to Sheets |
- 📦 Bulk Downloads — Download all files from a Classroom assignment with one click.
- 🔓 Drive Bypass — Automatically handles Google Drive's "Download anyway" confirmation pages.
- 🔄 Multi-Account Support — Cycles through your Google accounts to find the one with access.
- 📊 Local Stats — See your download history right in the Extension popup.
- 📈 Real-time Dashboard — Monitor download events, success rates, and breakdowns by browser/OS/country.
- ⏱️ Time-Series Analytics — Hourly and daily granularity for trend analysis.
- 📋 Google Sheets Archive — Automated daily exports for long-term reporting.
- 🔒 Privacy-First — No PII collected. Only file types, durations, and success/fail status.
We collect anonymous usage metrics only—never your files, passwords, or personal information.
| ✅ We Collect | ❌ We Never Collect |
|---|---|
| File types (pdf, docx) | File contents |
| Browser & OS | Usernames or emails |
| Success/fail status | Google credentials |
| Country (from IP) | Browsing history |
📘 Full details in PRIVACY.md
Found a bug? Have a suggestion? We'd love to hear from you.
- GitHub Issues: Open an Issue
- Feedback Form: Submit Feedback
This software is Proprietary & Source Available. Copyright © 2025 Adham Haitham. All Rights Reserved.
- ✅ You can: View, read, and use the extension for personal, non-commercial purposes.
- ❌ You cannot: Modify, edit, or build upon the source code.
- ❌ You cannot: Distribute modified versions or forks.
- ❌ You cannot: Use this code for commercial purposes.
For commercial inquiries or modification requests, please contact me directly.
Built with ☕ by Adham Haitham
A distributed analytics pipeline masquerading as a simple productivity tool.