DEV Community

Cover image for I Didn’t Want to Give Full GitHub Access — So I Built My Own LeetCode-to-GitHub Sync Chrome Extension
Rageeni Dawale
Rageeni Dawale

Posted on

I Didn’t Want to Give Full GitHub Access — So I Built My Own LeetCode-to-GitHub Sync Chrome Extension

I was practicing problems on LeetCode, and one day I thought:

What if my GitHub could reflect this automatically?

Not just as code, but as visible consistency. The contribution graph, the repository history — it would show that I was actively solving problems and improving over time. Anyone visiting my GitHub profile could see my LeetCode work without me manually uploading each solution.

The idea was simple: accepted submissions on LeetCode should automatically appear in GitHub.


The existing solutions didn’t feel right

There are already Chrome extensions that do this. But when I looked into them, I noticed something that made me uncomfortable.

Most of them required:

  • Full read/write access to all my GitHub repositories
  • Logging into my LeetCode account through the extension

This felt like giving too much control to a third-party tool.

Even if they were trustworthy, granting broad access when the extension only needed to write to a single repository didn’t feel right.

So instead of using an existing tool, I decided to build my own.


The core idea: minimal permissions, maximum control

I wanted an extension that would:

  • Detect accepted LeetCode submissions
  • Read the solution directly from the page
  • Push it to GitHub automatically
  • Require access to only one repository

And importantly, it should work without needing to log into LeetCode through the extension itself.

LeetCode already displays the submitted solution in the browser. The extension simply reads the code from the page DOM — no login handling or unnecessary permissions required.

For GitHub authentication, I used fine-grained personal access tokens. This allowed the extension to access only the repository I explicitly permitted, instead of requesting access to everything.

This approach gave me precise control over what the extension could and could not access.


How the extension works

The extension is built using Chrome Extension Manifest V3 and integrates with the GitHub REST API.

When a submission is accepted on LeetCode, the extension:

  1. Detects the accepted state
  2. Extracts the solution code and language
  3. Creates a properly named file
  4. Pushes it to the configured GitHub repository

Solutions are organized by language, making the repository clean and easy to navigate.

What I found most interesting was how different pieces came together — browser DOM access, extension architecture, and GitHub API integration — to automate something that was previously manual.


Challenges I faced while building it

What sounded simple initially turned out to involve several practical challenges, especially since I didn’t have prior experience building Chrome extensions.

Reading code reliably from a dynamic editor

LeetCode uses a browser-based editor where content is rendered dynamically.

This meant I couldn’t just query the DOM once and assume the solution would be available. I had to ensure that:

  • the submission was actually accepted
  • the editor content was fully rendered
  • the correct code and language were extracted

Understanding how the editor updated the DOM was essential to making the extension reliable.

Detecting accepted submissions at the right time

Timing was another challenge.

The extension needed to sync the solution only after it was accepted — not before, and not multiple times.

If the extension ran too early, it could miss the correct state or extract incomplete information. This required carefully detecting when the accepted state was present.

Preventing duplicate uploads

Another issue was avoiding duplicate uploads.

If the page was refreshed or revisited, the extension might try to upload the same solution again.

I had to ensure that the extension didn’t repeatedly sync the same submission, keeping the repository clean and accurate.

Extracting additional metadata like difficulty

Extracting information like problem difficulty was less straightforward than expected.

Since this data is part of the dynamically rendered page, it required careful inspection of the DOM structure to extract it reliably.

Learning Chrome Extension architecture and Manifest V3

This was my first time working with Chrome extensions and Manifest V3.

Manifest V3 uses service workers instead of persistent background scripts, which means everything is event-driven rather than continuously running.

Understanding how content scripts, background service workers, and extension storage worked together took time, but it was one of the most valuable parts of the project.


Publishing it made it real

Initially, this was just a personal tool.

But later, I decided to publish it on the Chrome Web Store.

Seeing it live felt different from pushing code to GitHub. It was no longer just a private experiment — it was something others could actually use.


Why I chose fine-grained tokens (for now)

Right now, the extension uses fine-grained personal access tokens for GitHub authentication.

This was a deliberate choice.

As an MVP, this approach allowed:

  • limiting access to a single repository
  • avoiding broad repository permissions
  • keeping the architecture simple without requiring a backend server

A more complete solution would use GitHub Apps, which provide a better authentication flow and more structured permissions.

That’s something I plan to explore in future versions.


What I want to improve next

There are several improvements I’d like to add:

  • Supporting historical LeetCode submissions
  • Improving the authentication flow
  • Moving to GitHub Apps for better permission handling
  • Making the setup process more user-friendly

These changes would make the extension both more secure and easier to use.


Why this project mattered to me

This started with a simple motivation: I wanted my GitHub to reflect the work I was already doing.

But building it taught me much more than I expected.

It helped me understand:

  • how browser extensions interact with web applications
  • how to securely integrate with external APIs
  • how to design tools with minimal permissions
  • how to build and ship something end-to-end

More importantly, it reinforced the idea that small personal frustrations can lead to meaningful projects.

Sometimes the best projects come from solving your own problems.

This was one of those projects.


If you're interested in the implementation, here's the source code:

GitHub repository:
https://github.com/rageenidawale/linkcode-leetcode-github-sync

Chrome Web Store:
https://chromewebstore.google.com/detail/linkcode-leetcode-github/dglnhlkedekgdkdpmjollhabaomlgalc

Top comments (0)