# Shimeji NFT Chrome Extension

A small Chrome extension that adds a digital mascot (a "shimeji") to web pages. The mascot either follows your mouse pointer or wanders around the browser window when idle. Different mascots can be unlocked by proving ownership of an NFT in your Ethereum wallet.

## Features

- **Pointer follow / wander:** Mascots follow the pointer while you move, and wander autonomously when idle.
- **NFT-locked mascots:** Certain mascots unlock only if you hold a specified Ethereum NFT in your connected wallet (MetaMask compatible).
- **Lightweight:** Minimal permissions and a simple UI for toggling mascots and settings.

## Quick install (dev mode)

1. Open Chrome and go to `chrome://extensions`.
2. Enable **Developer mode** (top-right).
3. Click **Load unpacked** and select this repository folder.
4. Open any webpage to see the mascot injected (or open [dapp.html](dapp.html) / [popup.html](popup.html) to interact with the extension UI).

## How it works (high level)

- Background script (`background.js`) listens for UI events and manages extension state.
- Content scripts (`content.js`, `dapp_content_script.js`) inject the mascot and handle pointer/wander behavior.
- `config.html` and `popup.html` provide a simple UI for toggling mascots and settings.
- NFT ownership is checked by connecting the user's Ethereum wallet (MetaMask) and querying on-chain ownership; a fallback/test mode is provided for local testing.

## Five testable milestones

Follow these steps to verify core functionality locally. Each milestone includes expected results and where to look in the code.

- **Milestone 1 — Install and show default mascot:**

  - Steps: Install the extension using the Quick install steps above. Open any page.
  - Expected result: A mascot appears on the page and wanders around.
  - Files: See [content.js](content.js) and [manifest.json](manifest.json).

- **Milestone 2 — Pointer follow behavior:**

  - Steps: Move your mouse around the page. Observe the mascot's motion.
  - Expected result: While you move the pointer, the mascot follows the cursor smoothly; when you stop moving the pointer, after a short delay the mascot returns to wandering mode.
  - Files: Behavior implemented in [content.js](content.js) and helper logic in [dapp_content_script.js](dapp_content_script.js).

- **Milestone 3 — Toggle mascots via UI:**

  - Steps: Open the extension popup via the toolbar icon (or open [popup.html](popup.html) directly). Select a different mascot if available.
  - Expected result: The selected mascot replaces the current one on the page.
  - Files: See [popup.html](popup.html) and [popup.js](popup.js) for selection flow; mascot assets live in `characters/` and `icons/`.

- **Milestone 4 — Simulate NFT unlock (local/test mode):**

  - Steps: For quick local testing, open [config.html](config.html). Use the provided test toggle (or localStorage flag) to mark a mascot as "unlocked" without connecting a wallet.
  - Expected result: The previously locked mascot becomes selectable and appears when chosen.
  - Files: See [config.html](config.html) and [config.js](config.js); search for a test/unlock flag or `localStorage` usage in these files.

- **Milestone 5 — Wallet-check NFT unlock (MetaMask):**
  - Steps: Open [dapp.html](dapp.html) and click the button to connect your wallet. Follow prompts to connect MetaMask. The dapp checks the chain for token ownership and reports unlocked mascots.
  - Expected result: If your connected wallet holds the required NFT, the extension marks the corresponding mascot as unlocked and it becomes selectable. If not, you'll see a "locked" state.
  - Files: Connection and ownership check live in [dapp_content_script.js](dapp_content_script.js) and [dapp.js](dapp.js). Wallet connect UI exists in [dapp.html](dapp.html).

## Architecture Note: Externally Hosted Pages

**Important:** The wallet connection pages are hosted on Vercel (not served from the extension).

### Hosted on Vercel:
- `index.html` / `index.js` - Main wallet connection and character selection page
- `dapp.html` / `dapp.js` - Full marketplace interface (legacy, may redirect to shimeji.dev)

### Why external hosting?
- MetaMask and other wallets only inject into http/https pages, NOT chrome-extension:// pages
- External pages do NOT have access to Chrome extension APIs (`chrome.runtime`, etc.)
- Communication happens via `window.postMessage` through the content script bridge

### Message Flow:
```
index.js (Vercel) <-> dapp_content_script.js (injected) <-> background.js (extension)
```

### When updating:
1. Deploy updated files to Vercel
2. Reload the extension in `chrome://extensions` to update content scripts and background.js

## Developer notes

- **Background script:** [background.js](background.js) — handles extension-wide events and NFT ownership checks.
- **Content injection & behavior:** [content.js](content.js) (mascot rendering) and [dapp_content_script.js](dapp_content_script.js) (message bridge for Vercel-hosted dapp).
- **Popup UI:** [popup.html](popup.html) + [popup.js](popup.js) + [popup.css](popup.css).
- **Config / test UI:** [config.html](config.html) + [config.js](config.js).
- **Manifest:** [manifest.json](manifest.json) — permissions and content script definitions.

## Testing tips

- If MetaMask won't connect in a local file context, host `dapp.html` with a tiny static server, e.g.:

```bash
python3 -m http.server 8080
# then open http://localhost:8080/dapp.html
```

- For rapid testing of NFT-locked behavior, use the local/test toggle in `config.html` to avoid on-chain queries.

## Next steps / enhancements

- Add more mascots and animations in `characters/`.
- Cache NFT ownership checks to reduce RPC calls.
- Add settings for mascot size, z-index, and persistence across tabs.

If you'd like, I can also run a quick check of the extension files or add a short demo script to toggle unlocks automatically.
