Loading drafts from local storage...
diff --git a/browser-extension/src/entrypoints/content/config.ts b/browser-extension/src/lib/config.ts
similarity index 100%
rename from browser-extension/src/entrypoints/content/config.ts
rename to browser-extension/src/lib/config.ts
diff --git a/browser-extension/src/lib/enhancer.ts b/browser-extension/src/lib/enhancer.ts
new file mode 100644
index 0000000..82ac2eb
--- /dev/null
+++ b/browser-extension/src/lib/enhancer.ts
@@ -0,0 +1,26 @@
+import type { OverType } from '../overtype/mock-overtype'
+
+/**
+ * stores enough info about the location of a draft to:
+ * - display it in a table
+ * - reopen the draft in-context
+ */
+export interface CommentSpot {
+  unique_key: string
+  type: string
+}
+
+/** wraps the textareas of a given platform with Gitcasso's enhancements */
+export interface CommentEnhancer
 {
+  /** guarantees to only return a type within this list */
+  forSpotTypes(): string[]
+  /**
+   * whenever a new `textarea` is added to any webpage, this method is called.
+   * if we return non-null, then we become the handler for that text area.
+   */
+  tryToEnhance(textarea: HTMLTextAreaElement): [OverType, Spot] | null
+
+  tableIcon(spot: Spot): string
+  tableTitle(spot: Spot): string
+  buildUrl(spot: Spot): string
+}
diff --git a/browser-extension/src/lib/enhancers/github.ts b/browser-extension/src/lib/enhancers/github.ts
new file mode 100644
index 0000000..a055263
--- /dev/null
+++ b/browser-extension/src/lib/enhancers/github.ts
@@ -0,0 +1,109 @@
+import { OverType } from '../../overtype/mock-overtype'
+import type { CommentEnhancer, CommentSpot } from '../enhancer'
+
+const GITHUB_SPOT_TYPES = [
+  'GH_ISSUE_NEW',
+  'GH_PR_NEW',
+  'GH_ISSUE_ADD_COMMENT',
+  'GH_PR_ADD_COMMENT',
+  /* TODO
+  'GH_ISSUE_EDIT_COMMENT',
+  'GH_PR_EDIT_COMMENT',
+  'GH_PR_CODE_COMMENT',
+  */
+] as const
+
+export type GitHubSpotType = (typeof GITHUB_SPOT_TYPES)[number]
+
+export interface GitHubSpot extends CommentSpot {
+  type: GitHubSpotType // Override to narrow from string to specific union
+  domain: string
+  slug: string // owner/repo
+  number?: number | undefined // issue/PR number, undefined for new issues and PRs
+}
+
+export class GitHubEnhancer implements CommentEnhancer {
+  forSpotTypes(): string[] {
+    return [...GITHUB_SPOT_TYPES]
+  }
+
+  tryToEnhance(textarea: HTMLTextAreaElement): [OverType, GitHubSpot] | null {
+    // Only handle GitHub domains
+    if (!window.location.hostname.includes('github')) {
+      return null
+    }
+
+    const pathname = window.location.pathname
+
+    // Parse GitHub URL structure: /owner/repo/issues/123 or /owner/repo/pull/456
+    const match = pathname.match(/^\/([^/]+)\/([^/]+)(?:\/(issues|pull)\/(\d+))?/)
+    if (!match) return null
+
+    const [, owner, repo, urlType, numberStr] = match
+    const slug = `${owner}/${repo}`
+    const number = numberStr ? parseInt(numberStr, 10) : undefined
+
+    // Determine comment type
+    let type: GitHubSpotType
+
+    if (pathname.includes('/issues/new')) {
+      type = 'GH_ISSUE_NEW'
+    } else if (pathname.includes('/compare/') || pathname.endsWith('/compare')) {
+      type = 'GH_PR_NEW'
+    } else if (urlType && number) {
+      if (urlType === 'issues') {
+        type = 'GH_ISSUE_ADD_COMMENT'
+      } else {
+        type = 'GH_PR_ADD_COMMENT'
+      }
+    } else {
+      return null
+    }
+
+    // Generate unique key based on context
+    let unique_key = `github:${slug}`
+    if (number) {
+      unique_key += `:${urlType}:${number}`
+    } else {
+      unique_key += ':new'
+    }
+
+    const spot: GitHubSpot = {
+      domain: window.location.hostname,
+      number,
+      slug,
+      type,
+      unique_key,
+    }
+    const overtype = new OverType(textarea)
+    return [overtype, spot]
+  }
+
+  tableTitle(spot: GitHubSpot): string {
+    const { slug, number } = spot
+    if (number) {
+      return `Comment on ${slug} #${number}`
+    }
+    return `New ${window.location.pathname.includes('/issues/') ? 'issue' : 'PR'} in ${slug}`
+  }
+
+  tableIcon(spot: GitHubSpot): string {
+    switch (spot.type) {
+      case 'GH_ISSUE_NEW':
+      case 'GH_ISSUE_ADD_COMMENT':
+        return '🐛' // Issue icon
+      case 'GH_PR_NEW':
+      case 'GH_PR_ADD_COMMENT':
+        return '🔄' // PR icon
+    }
+  }
+
+  buildUrl(spot: GitHubSpot): string {
+    const baseUrl = `https://${spot.domain}/${spot.slug}`
+    if (spot.number) {
+      const type = spot.type.indexOf('ISSUE') ? 'issues' : 'pull'
+      return `${baseUrl}/${type}/${spot.number}`
+    }
+    return baseUrl
+  }
+}
diff --git a/browser-extension/src/entrypoints/content/logger.ts b/browser-extension/src/lib/logger.ts
similarity index 100%
rename from browser-extension/src/entrypoints/content/logger.ts
rename to browser-extension/src/lib/logger.ts
diff --git a/browser-extension/src/lib/registries.ts b/browser-extension/src/lib/registries.ts
new file mode 100644
index 0000000..467043a
--- /dev/null
+++ b/browser-extension/src/lib/registries.ts
@@ -0,0 +1,62 @@
+import type { OverType } from '../overtype/mock-overtype'
+import type { CommentEnhancer, CommentSpot } from './enhancer'
+import { GitHubEnhancer } from './enhancers/github'
+
+export interface EnhancedTextarea {
+  textarea: HTMLTextAreaElement
+  spot: T
+  handler: CommentEnhancer
+  overtype: OverType
+}
+
+export class EnhancerRegistry {
+  private enhancers = new Set>()
+
+  constructor() {
+    // Register all available handlers
+    this.register(new GitHubEnhancer())
+  }
+
+  private register(handler: CommentEnhancer): void {
+    this.enhancers.add(handler)
+  }
+
+  tryToEnhance(textarea: HTMLTextAreaElement): EnhancedTextarea | null {
+    for (const handler of this.enhancers) {
+      try {
+        const result = handler.tryToEnhance(textarea)
+        if (result) {
+          const [overtype, spot] = result
+          return { handler, overtype, spot, textarea }
+        }
+      } catch (error) {
+        console.warn('Handler failed to identify textarea:', error)
+      }
+    }
+    return null
+  }
+
+  getEnhancerCount(): number {
+    return this.enhancers.size
+  }
+}
+
+export class TextareaRegistry {
+  private textareas = new Map>()
+
+  register(textareaInfo: EnhancedTextarea): void {
+    this.textareas.set(textareaInfo.textarea, textareaInfo)
+    // TODO: register as a draft in progress with the global list
+  }
+
+  unregisterDueToModification(textarea: HTMLTextAreaElement): void {
+    if (this.textareas.has(textarea)) {
+      // TODO: register as abandoned or maybe submitted with the global list
+      this.textareas.delete(textarea)
+    }
+  }
+
+  get(textarea: HTMLTextAreaElement): EnhancedTextarea | undefined {
+    return this.textareas.get(textarea)
+  }
+}
diff --git a/browser-extension/src/overtype/mock-overtype.ts b/browser-extension/src/overtype/mock-overtype.ts
new file mode 100644
index 0000000..fec648c
--- /dev/null
+++ b/browser-extension/src/overtype/mock-overtype.ts
@@ -0,0 +1,44 @@
+/**
+ * Mock implementation of Overtype for development
+ * This wraps a textarea and provides a minimal interface
+ */
+export class OverType {
+  public element: HTMLTextAreaElement
+  public instanceId: number
+  public initialized: boolean = true
+
+  private static instanceCount = 0
+
+  constructor(target: HTMLTextAreaElement) {
+    this.element = target
+    this.instanceId = ++OverType.instanceCount
+
+    // Store reference on the element
+    ;(target as any).overTypeInstance = this
+
+    // Apply basic styling or enhancement
+    this.enhance()
+  }
+
+  private enhance(): void {
+    // Mock enhancement - could add basic styling, event handlers, etc.
+    this.element.style.fontFamily =
+      'Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace'
+    this.element.style.fontSize = '14px'
+    this.element.style.lineHeight = '1.5'
+  }
+
+  getValue(): string {
+    return this.element.value
+  }
+
+  setValue(value: string): void {
+    this.element.value = value
+  }
+
+  destroy(): void {
+    // Clean up any enhancements
+    delete (this.element as any).overTypeInstance
+    this.initialized = false
+  }
+}
diff --git a/browser-extension/tests/lib/enhancers/__snapshots__/github.test.ts.snap b/browser-extension/tests/lib/enhancers/__snapshots__/github.test.ts.snap
new file mode 100644
index 0000000..fa2f132
--- /dev/null
+++ b/browser-extension/tests/lib/enhancers/__snapshots__/github.test.ts.snap
@@ -0,0 +1,11 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`GitHubHandler > should create correct GitHubContext spot for PR comment > github-pr-517-spot 1`] = `
+{
+  "domain": "github.com",
+  "number": 517,
+  "slug": "diffplug/selfie",
+  "type": "GH_PR_ADD_COMMENT",
+  "unique_key": "github:diffplug/selfie:pull:517",
+}
+`;
diff --git a/browser-extension/tests/lib/enhancers/github.test.ts b/browser-extension/tests/lib/enhancers/github.test.ts
new file mode 100644
index 0000000..2ec59ef
--- /dev/null
+++ b/browser-extension/tests/lib/enhancers/github.test.ts
@@ -0,0 +1,92 @@
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { EnhancerRegistry, TextareaRegistry } from '../../../src/lib/registries'
+
+// Mock WXT's defineContentScript global
+vi.stubGlobal('defineContentScript', vi.fn())
+
+describe('GitHubHandler', () => {
+  let enhancers: EnhancerRegistry
+  let enhancedTextareas: TextareaRegistry
+  let mockTextarea: HTMLTextAreaElement
+
+  beforeEach(() => {
+    // Reset DOM and registries for each test
+    document.body.innerHTML = ''
+    enhancers = new EnhancerRegistry()
+    enhancedTextareas = new TextareaRegistry()
+
+    // Mock window.location for GitHub PR page
+    Object.defineProperty(window, 'location', {
+      value: {
+        hostname: 'github.com',
+        href: 'https://github.com/diffplug/selfie/pull/517',
+        pathname: '/diffplug/selfie/pull/517',
+      },
+      writable: true,
+    })
+
+    // Create a mock textarea element that mimics GitHub's PR comment box
+    mockTextarea = document.createElement('textarea')
+    mockTextarea.name = 'comment[body]'
+    mockTextarea.placeholder = 'Leave a comment'
+    mockTextarea.className = 'form-control markdown-body'
+
+    // Add it to a typical GitHub comment form structure
+    const commentForm = document.createElement('div')
+    commentForm.className = 'js-new-comment-form'
+    commentForm.appendChild(mockTextarea)
+    document.body.appendChild(commentForm)
+  })
+
+  it('should identify GitHub PR textarea and register it in TextareaRegistry', () => {
+    // Simulate the content script's enhanceMaybe function
+    const enhancedTextarea = enhancers.tryToEnhance(mockTextarea)
+
+    expect(enhancedTextarea).toBeTruthy()
+    expect(enhancedTextarea?.textarea).toBe(mockTextarea)
+    expect(enhancedTextarea?.spot.type).toBe('GH_PR_ADD_COMMENT')
+
+    // Register the enhanced textarea
+    if (enhancedTextarea) {
+      enhancedTextareas.register(enhancedTextarea)
+    }
+
+    // Verify it's in the registry
+    const registeredTextarea = enhancedTextareas.get(mockTextarea)
+    expect(registeredTextarea).toBeTruthy()
+    expect(registeredTextarea?.textarea).toBe(mockTextarea)
+  })
+
+  it('should create correct GitHubContext spot for PR comment', () => {
+    const enhancedTextarea = enhancers.tryToEnhance(mockTextarea)
+
+    expect(enhancedTextarea).toBeTruthy()
+
+    // Snapshot test on the spot value
+    expect(enhancedTextarea?.spot).toMatchSnapshot('github-pr-517-spot')
+
+    // Also verify specific expected values
+    expect(enhancedTextarea?.spot).toMatchObject({
+      domain: 'github.com',
+      number: 517,
+      slug: 'diffplug/selfie',
+      type: 'GH_PR_ADD_COMMENT',
+      unique_key: 'github:diffplug/selfie:pull:517',
+    })
+  })
+
+  it('should not enhance textarea on non-GitHub pages', () => {
+    // Change location to non-GitHub site
+    Object.defineProperty(window, 'location', {
+      value: {
+        hostname: 'example.com',
+        href: 'https://example.com/some/page',
+        pathname: '/some/page',
+      },
+      writable: true,
+    })
+
+    const enhancedTextarea = enhancers.tryToEnhance(mockTextarea)
+    expect(enhancedTextarea).toBeNull()
+  })
+})
diff --git a/browser-extension/tests/setup.ts b/browser-extension/tests/setup.ts
index 1171022..a9d0dd3 100644
--- a/browser-extension/tests/setup.ts
+++ b/browser-extension/tests/setup.ts
@@ -1,38 +1 @@
 import '@testing-library/jest-dom/vitest'
-import { vi } from 'vitest'
-
-// Mock browser APIs
-interface GlobalWithBrowser {
-  browser: {
-    runtime: {
-      sendMessage: ReturnType
-      onMessage: {
-        addListener: ReturnType
-      }
-    }
-  }
-  chrome: GlobalWithBrowser['browser']
-}
-
-const globalWithBrowser = global as unknown as GlobalWithBrowser
-
-globalWithBrowser.browser = {
-  runtime: {
-    onMessage: {
-      addListener: vi.fn(),
-    },
-    sendMessage: vi.fn(),
-  },
-}
-
-globalWithBrowser.chrome = globalWithBrowser.browser
-
-// Mock console methods to reduce noise in tests
-global.console = {
-  ...console,
-  debug: vi.fn(),
-  error: vi.fn(),
-  info: vi.fn(),
-  log: vi.fn(),
-  warn: vi.fn(),
-}
diff --git a/browser-extension/tsconfig.json b/browser-extension/tsconfig.json
index a914c1f..90169d5 100644
--- a/browser-extension/tsconfig.json
+++ b/browser-extension/tsconfig.json
@@ -42,5 +42,5 @@
   },
   "exclude": ["node_modules", ".output", "dist"],
   "extends": "./.wxt/tsconfig.json",
-  "include": ["src/entrypoints/**/*", "*.config.ts", ".wxt/wxt.d.ts", "tests/**/*"]
+  "include": ["src/**/*", "*.config.ts", ".wxt/wxt.d.ts", "tests/**/*"]
 }
diff --git a/browser-extension/vitest.config.ts b/browser-extension/vitest.config.ts
index d247fc3..af7d365 100644
--- a/browser-extension/vitest.config.ts
+++ b/browser-extension/vitest.config.ts
@@ -1,14 +1,8 @@
-import path from 'node:path'
 import { defineConfig } from 'vitest/config'
+import { WxtVitest } from 'wxt/testing'
 
 export default defineConfig({
-  resolve: {
-    alias: {
-      '@': path.resolve(__dirname, './entrypoints'),
-      '@content': path.resolve(__dirname, './entrypoints/content'),
-      '@utils': path.resolve(__dirname, './entrypoints/content/utils'),
-    },
-  },
+  plugins: [WxtVitest()],
   test: {
     coverage: {
       exclude: [
diff --git a/browser-extension/wxt.config.ts b/browser-extension/wxt.config.ts
index 0514d1a..edc2589 100644
--- a/browser-extension/wxt.config.ts
+++ b/browser-extension/wxt.config.ts
@@ -3,7 +3,7 @@ import { defineConfig } from 'wxt'
 export default defineConfig({
   manifest: {
     description:
-      'Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly places).',
+      'Syntax highlighting and autosave for comments on GitHub (and other other markdown-friendly websites).',
     host_permissions: ['https://*/*', 'http://*/*'],
     icons: {
       16: '/icons/icon-16.png',