- Init repo, MIT license,
.gitignore, README stub. - Set up Manifest V3 skeleton (
manifest.json) with zero permissions initially — add them one at a time as each phase actually needs them, so the permission list stays honest and auditable. - Pick build tooling: Vite +
@crxjs/vite-plugin(handles MV3 hot-reload well) or plain esbuild if you want minimal deps. Given your stack preferences, Vite is the better fit. - TypeScript config, strict mode on — this extension touches a lot of external data shapes (GitHub API, DOM scraping) where types catch real bugs.
- Load unpacked in Chrome, confirm it installs with an empty popup. This is your "hello world" checkpoint.
Everything downstream — settings, logs, queue — reads/writes here, so get the schema right first.
- Define TypeScript interfaces for
Settings,ProblemRecord,SyncLogEntry,RetryQueueItem(per the PRD data model). - Wrap
chrome.storage.localin a small typed module (storage/db.ts) withget<T>(key),set<T>(key, value), namespaced keys (settings,problems:<id>,log:<date>,queue). - Add a migration/versioning stub now (
schemaVersionfield) — cheap to add early, painful to retrofit later. - Unit test the wrapper against a mocked
chrome.storage(e.g.sinon-chromeor a hand-rolled mock).
This is the highest-risk integration (auth, rate limits, encoding) — build and test it standalone before wiring it to LeetCode.
- Options page field for PAT entry. Store encrypted-at-rest via
chrome.storage.local(Chrome encrypts local storage on disk at the OS level; document this honestly rather than implying custom encryption). github/client.ts: functions fortestConnection(pat, repo)— GET repo metadata, confirm Contents R/W scope.getFile(path)— GET contents endpoint, capturesha(required for updates).putFile(path, content, message, sha?)— PUT contents endpoint, base64-encode content.listDirectory(path)— for duplicate/version detection later.
- Handle GitHub error codes explicitly: 401 (bad token), 403 (rate limit), 404 (repo/path missing), 409 (sha conflict from concurrent edit).
- Manual test: hardcode a test repo, push a dummy file via the popup, confirm it lands correctly with the right commit message.
Checkpoint: can manually trigger an upload to a real repo. Nothing LeetCode-related exists yet.
The riskiest and most fragile part per your own Problem Statement — isolate it behind the PlatformAdapter interface from day one so a UI change only breaks this file.
- Implement
platforms/leetcode/adapter.tsagainst thePlatformAdapterinterface (detectSubmission,extractProblem,extractCode,extractLanguage,extractDifficulty,extractMetadata). - Detection approach — prefer network interception over DOM scraping where possible: LeetCode's submission result comes back via an XHR/fetch response; a content script can listen for that response (via
chrome.webRequestisn't available for reading bodies in MV3 without extra permissions, so more realistically: inject a small page-context script that monkey-patchesfetch/XHRand posts results to the content script viawindow.postMessage). This is more resilient to CSS/DOM churn than selector-scraping, which directly addresses the reliability problem in your PRD. - Fallback DOM scraping for fields not present in the network payload (e.g. confirming "Accepted" badge visibly rendered, extracting the code editor's current content if not in the response).
- Extract: title, slug/id, difficulty, language, runtime, memory, tags (if available), code, submission timestamp, URL.
- Test against real accepted submissions across a few difficulty/language combinations. Log raw extracted objects to console during dev — don't wire to GitHub yet.
Checkpoint: open dev console on a LeetCode submission page, see a correctly-populated ProblemRecord object logged after every Accepted result.
github/readme-generator.ts: given all storedProblemRecords, generate markdown — header, stats (total solved, difficulty breakdown), and a problem table.- Link resolution: dynamically link to the correctly resolved paths for all uploaded solutions based on the active
versionModeandfolderStructure. - Regenerate and
putFilethe README after every successful sync in the Sync Engine (Phase 4). - Guard against races: if two syncs happen in quick succession, make sure the README's
shais re-fetched before each update (409 handling from Phase 2 matters here).
Checkpoint: after a handful of syncs, README in the repo accurately reflects solved count, difficulty breakdown, and links to the right file versions.
- Simple template engine:
{title},{difficulty},{language},{runtime},{memory}placeholders substituted into a user-defined string (default template from the PRD). - Options page field for editing the template, with the default pre-filled and a live preview.
- Wire into Sync Engine's
putFilecall.
storagealready has aqueuenamespace (Phase 1). On anyputFilefailure in Phase 4, push{ problemId, reason, timestamp }.- Background worker: on extension startup and on a periodic alarm (
chrome.alarms, e.g. every 5 min), attempt to flush the queue — re-run the sync for each queued item. - Respect GitHub rate-limit headers (
X-RateLimit-Reset) — don't hammer retries into an active rate limit. - Remove from queue on success; cap retry attempts (e.g. 5) and surface permanently-failed items in the popup log rather than retrying forever silently.
- Dashboard: today's sync log (✔/✖ with reasons, per PRD), quick stats, manual "Sync Current Problem" button (re-runs extraction on the currently open tab if it's a LeetCode submission page).
- Wire to the storage layer read-only for logs/stats, and to the Sync Engine for the manual trigger.
- Keep this thin — no business logic in the UI layer, it only reads storage and dispatches messages to the background worker.
- Redesigned the Options, Onboarding, and Popup pages with a modern glassmorphic dark theme.
- Added interactive Lightbox for setup guide images.
- Automatically fetch the manifest version for the UI footer.
- Error handling passes applied.
Checkpoint: Full first-run flow works end to end and looks beautiful. Ready for Phase 11.
Go back through Phases 2–7 and make sure every case in the PRD's error table is actually handled, not just the happy path:
- Rate limit → retry (Phase 7 covers this — verify).
- Network failure → queue (verify offline behavior specifically, e.g. laptop sleep mid-sync).
- Repository deleted → detect via 404 on next sync, surface a clear "reconnect repository" notification rather than silent retry-forever.
- Invalid token → detect via 401, prompt reconnect in popup, don't just log and drop.
- Implement GraphQL/API scraping to fetch all previously "Accepted" submissions from LeetCode.
- Inject scraping script into a foreground tab to securely use CSRF cookies.
- Batch queue these historical solutions through the
sync-engineto prevent duplicate spam and handle rate limiting gracefully.
- Refactor or extend
PlatformAdapterto handle sites like GeeksForGeeks or HackerRank. - Implement specific
GeeksForGeeksAdapterincluding DOM observation and code extraction. - Update Options UI so users can select which platforms to sync from.
- Manual test matrix: multiple languages, all 3 difficulties, all 4 folder structures, re-submission (duplicate + version-bump paths), rate-limit simulation (mock 403 response), token revocation mid-session.
- Memory/perf sanity check — nothing in this PRD's original targets was load-bearing, but do confirm the popup doesn't lag and the content script isn't leaking listeners on SPA navigation (LeetCode is a SPA — watch for content script re-injection issues across problem navigations).
- Fresh-profile install test — the exact first-run flow a new user hits, no dev-console assists.
- Write the store listing emphasizing the security model (fine-grained PAT, single repo, no OAuth, no telemetry) — this is your actual differentiator, lead with it.
- Privacy policy page (even a static one) — required for Web Store listing, and directly reinforces the trust positioning from your Guiding Philosophy section.
- Icons, screenshots, promotional tile.
- Submit for review; MV3 extensions with
storage+ host permissions togithub.com/leetcode.comtypically get flagged for manual review — expect a review cycle, not instant approval.
Phase 0 → scaffolding
Phase 1 → storage layer
Phase 2 → GitHub client ┐ build/test independently
Phase 3 → LeetCode adapter ┘
Phase 4 → sync engine (joins 1+2+3)
Phase 5 → README generator
Phase 6 → commit templating
Phase 7 → retry queue
Phase 8 → GitHub Actions CI
Phase 9 → popup UI
Phase 10 → options page
Phase 11 → sync past submissions
Phase 12 → multi platform support
Phase 13 → error handling & QA
Phase 14 → Web Store packaging
Phases 2 and 3 can be built in parallel (or in either order) since neither depends on the other — they only meet at Phase 4. Everything from Phase 5 onward is strictly sequential.
