All projects

Project 07 Chrome Extension

Ember: LeetCode Pet

A small fire that lives in the corner of your LeetCode problems and goes out if you stop solving them. A pet, not a tracker: no streaks, no badges, nothing to lose.

Role
Solo build
Timeline
Sep 2026
Stack
JavaScript · Chrome MV3 · Shadow DOM
Status
Not on the Web Store yet
Ember’s five heat states side by side, from blazing to cold

Overview

Ember is a Chrome extension that puts a small, living fire in the corner of every LeetCode problem. It gets brighter when you solve things and dimmer when you don’t, and that is the entire feedback loop.

It can’t die, can’t be lost and never nags; there are no notifications at all. Going quietly cold in the corner is the whole message.

The problem

Streak trackers turn practice into something to protect, and one missed day wipes out months. Ember works the other way round: most of its income comes from problems you haven’t solved before, so grinding the same three keeps it alive but never makes it rich.

How it works

  • Paid on Accepted, and only on Accepted. A script on the page reads each submission’s verdict. Sparks are set by difficulty (12, 30 or 70) and by the kind of solve: ×1.5 for a new problem accepted on the first try, ×0.6 for re-solving on a later day, and nothing for the same day again.
  • A new approach counts. A re-solve pays the full rate only if its runtime differs from every runtime already banked for that problem by at least 3 ms and 25%. Swapping a nested loop for a hash map clears that; re-running the same code doesn’t.
  • Heat without timers. Heat runs from 0 to 100 and falls 20 a day, computed lazily from the gap since it was last read. There’s no alarm to keep alive, because Manifest V3 service workers are killed after 30 idle seconds.
  • Fuel and cosmetics. Sparks buy fuel to put heat back (five staples and ten specials with effects) or nine purely decorative cosmetics.
  • It stays where you put it. Drag it anywhere and every open tab follows. On a different-sized monitor it keeps the same pixel gap from a nearby edge, or the same proportion of the window out in the open.

Key features

  • 01

    Lives on the page

    Sits in the code pane’s corner on every problem.

  • 02

    Five heat states

    From blazing to cold, and never dead.

  • 03

    An honest economy

    New problems pay most; farming one doesn’t.

  • 04

    Fuel & wardrobe

    A shop for heat, and cosmetics with no stats.

  • 05

    Month grid

    A calendar of the days you solved something.

  • 06

    Private

    Only storage and leetcode.com. Nothing leaves your machine.

Challenges & what I learned

The hardest bug was invisible. The pet’s position was set on its shadow host and never arrived, on any layout: the stylesheet opens with :host { all: initial !important } to stop LeetCode restyling it, and for !important declarations the cascade between a shadow tree and the page is inverted, so the shadow rule beat even an inline style. Nothing threw and nothing logged; the pet mounted perfectly and sat off-screen.

The fix passes the position in as custom properties, which all doesn’t reset, and a self-check now compares where the host was told to go with where it actually landed. A 511-check test suite covers the economy, verdict parsing and placement.

What’s next

Publishing to the Chrome Web Store: the listing, screenshots and privacy policy are drafted, and the packaged build is ready.