Skip to content

Commit 10a4ed6

Browse files
JOHNJOHN
authored andcommitted
Fix window is not defined error in service worker
- Make Pubky Client initialization lazy (not in constructor) - Check for window availability before initializing Pubky Client - Throw helpful error if Pubky operations attempted in service worker context - Background script should use offscreen document for Pubky operations
1 parent f5cf779 commit 10a4ed6

23 files changed

+3076
-2
lines changed

docs/API_REFERENCE 2.md

Lines changed: 586 additions & 0 deletions
Large diffs are not rendered by default.

docs/ARCHITECTURE 2.md

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# Graphiti Architecture
2+
3+
This document describes the system architecture of the Graphiti Chrome Extension.
4+
5+
## Overview
6+
7+
Graphiti is a Chrome Extension built on Manifest V3 that enables users to interact with web pages through drawing, annotations, bookmarks, and tags, all synchronized via the Pubky decentralized network.
8+
9+
## High-Level Architecture
10+
11+
```
12+
┌─────────────────────────────────────────────────────────────────────┐
13+
│ Chrome Browser │
14+
├─────────────────────────────────────────────────────────────────────┤
15+
│ │
16+
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
17+
│ │ Popup │ │ Side Panel │ │ Profile Page │ │
18+
│ │ │ │ │ │ │ │
19+
│ │ - Auth UI │ │ - Feed viewer │ │ - Profile │ │
20+
│ │ - Quick actions │ │ - Post list │ │ rendering │ │
21+
│ │ - Profile edit │ │ - Annotations │ │ │ │
22+
│ └────────┬─────────┘ └────────┬─────────┘ └──────────────────┘ │
23+
│ │ │ │
24+
│ └─────────┬───────────┘ │
25+
│ ▼ │
26+
│ ┌──────────────────────────────────────────────────────────────┐ │
27+
│ │ Background Script │ │
28+
│ │ (Service Worker) │ │
29+
│ │ │ │
30+
│ │ - Message routing │ │
31+
│ │ - Keyboard shortcuts │ │
32+
│ │ - Side panel control │ │
33+
│ │ - Storage coordination │ │
34+
│ └────────────────────────────┬─────────────────────────────────┘ │
35+
│ │ │
36+
│ ┌───────────────────┼───────────────────┐ │
37+
│ ▼ ▼ ▼ │
38+
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
39+
│ │ Content │ │ Content │ │ Content │ │
40+
│ │ Script │ │ Script │ │ Script │ │
41+
│ │ (Tab 1) │ │ (Tab 2) │ │ (Tab N) │ │
42+
│ │ │ │ │ │ │ │
43+
│ │ - Drawing │ │ - Drawing │ │ - Drawing │ │
44+
│ │ - Annotations │ │ - Annotations │ │ - Annotations │ │
45+
│ │ - URL links │ │ - URL links │ │ - URL links │ │
46+
│ └────────────────┘ └────────────────┘ └────────────────┘ │
47+
│ │
48+
└─────────────────────────────────────────────────────────────────────┘
49+
50+
│ HTTPS
51+
52+
┌───────────────────────────────────────────────┐
53+
│ External Services │
54+
│ │
55+
│ ┌─────────────────┐ ┌─────────────────┐ │
56+
│ │ Nexus API │ │ Pubky │ │
57+
│ │ │ │ Homeserver │ │
58+
│ │ - Post search │ │ │ │
59+
│ │ - User lookup │ │ - Data storage │ │
60+
│ │ - Social graph │ │ - Auth │ │
61+
│ └─────────────────┘ └─────────────────┘ │
62+
│ │
63+
└───────────────────────────────────────────────┘
64+
```
65+
66+
## Component Details
67+
68+
### Background Script (Service Worker)
69+
70+
**Location:** `src/background/background.ts`
71+
72+
The background script is the central coordinator:
73+
74+
- Handles Chrome extension lifecycle events
75+
- Routes messages between popup, content scripts, and sidepanel
76+
- Manages keyboard shortcuts (Alt+D for drawing, etc.)
77+
- Controls sidepanel opening/closing
78+
- Cannot access `window` or DOM (service worker limitation)
79+
80+
### Content Scripts
81+
82+
**Location:** `src/content/content.ts`
83+
84+
Injected into every web page:
85+
86+
- **DrawingManager**: Canvas overlay for drawing
87+
- **AnnotationManager**: Text selection and highlighting
88+
- **URL Linkifier**: Converts `pubky://` URLs to clickable buttons
89+
90+
### Popup
91+
92+
**Location:** `src/popup/`
93+
94+
Extension popup (400x500px):
95+
96+
- **AuthView**: QR code authentication
97+
- **MainView**: Logged-in interface with quick actions
98+
- **DebugPanel**: Log viewer
99+
- **ProfileEditor**: Profile editing form
100+
101+
### Side Panel
102+
103+
**Location:** `src/sidepanel/`
104+
105+
Feed viewer:
106+
107+
- **PostCard**: Displays posts about current URL
108+
- **AnnotationCard**: Displays annotations
109+
- **EmptyState**: Empty feed message
110+
111+
### Utilities
112+
113+
**Location:** `src/utils/`
114+
115+
Shared modules:
116+
117+
| Module | Responsibility |
118+
|--------|---------------|
119+
| `auth-sdk.ts` | Authentication via official Pubky SDK |
120+
| `crypto.ts` | Hashing, encoding, tokens |
121+
| `storage.ts` | Chrome storage wrapper |
122+
| `pubky-api-sdk.ts` | Homeserver operations |
123+
| `nexus-client.ts` | Nexus API queries |
124+
| `logger.ts` | Debug logging |
125+
126+
## Data Flow
127+
128+
### Authentication Flow
129+
130+
Authentication uses the official `@synonymdev/pubky` SDK for secure, decentralized identity.
131+
132+
**Homeserver Resolution:**
133+
The homeserver URL is derived directly from the user's public key using the `pubky://` protocol:
134+
```
135+
homeserver = 'pubky://' + publicKey.z32()
136+
```
137+
This ensures proper routing through the Pubky DHT without hardcoded server URLs.
138+
139+
**Auth Flow:**
140+
```
141+
1. User clicks "Sign In"
142+
2. Popup creates auth request via Pubky SDK (authRequest)
143+
3. SDK generates pubkyauth:// URL with relay and capabilities
144+
4. QR code displayed for scanning
145+
5. User scans with Pubky Ring mobile app
146+
6. SDK awaits response via authRequest.response()
147+
7. On approval, SDK returns authenticated PublicKey
148+
8. Session created with homeserver = 'pubky://' + publicKey.z32()
149+
9. Session stored in chrome.storage.local
150+
```
151+
152+
### Bookmark Flow
153+
154+
```
155+
1. User clicks bookmark button
156+
2. Popup sends CREATE_BOOKMARK to background
157+
3. Background/Popup creates Link Post on homeserver
158+
4. Background/Popup creates Bookmark referencing post
159+
5. Both indexed by Nexus
160+
6. Local storage updated
161+
```
162+
163+
### Drawing Flow
164+
165+
```
166+
1. User presses Alt+D
167+
2. Background sends TOGGLE_DRAWING to content script
168+
3. Content script shows canvas overlay
169+
4. User draws
170+
5. User saves (Save & Exit or Alt+D)
171+
6. Content script sends drawing data to background
172+
7. Background saves to chrome.storage.local
173+
8. Optional: Sync to homeserver
174+
```
175+
176+
### Feed Loading Flow
177+
178+
```
179+
1. Sidepanel opens
180+
2. Gets current tab URL
181+
3. Generates URL hash tag
182+
4. Queries Nexus API for posts with tag
183+
5. Renders PostCard for each result
184+
6. Also fetches annotations
185+
```
186+
187+
## Storage Architecture
188+
189+
### Local Storage (chrome.storage.local)
190+
191+
| Key | Data Type | Purpose |
192+
|-----|-----------|---------|
193+
| `session` | Session | Current auth session |
194+
| `bookmarks` | StoredBookmark[] | Local bookmarks |
195+
| `tags` | StoredTag[] | Local tags |
196+
| `profile` | ProfileData | Local profile |
197+
| `pubky_drawings` | {[url]: Drawing} | Drawings by URL |
198+
| `pubky_annotations` | Annotation[] | Local annotations |
199+
| `debugLogs` | LogEntry[] | Debug logs |
200+
201+
### Homeserver Storage (Pubky)
202+
203+
| Path | Data Type | Purpose |
204+
|------|-----------|---------|
205+
| `/pub/pubky.app/profile.json` | ProfileData | User profile |
206+
| `/pub/pubky.app/posts/{id}` | Post | Social posts |
207+
| `/pub/pubky.app/bookmarks/{id}` | Bookmark | Bookmarks |
208+
| `/pub/pubky.app/tags/{id}` | Tag | Tags |
209+
| `/pub/graphiti.dev/drawings/{hash}` | Drawing | Drawings |
210+
211+
## Message Protocol
212+
213+
Communication between components uses Chrome messaging:
214+
215+
```typescript
216+
// Send message
217+
chrome.runtime.sendMessage({
218+
type: 'MESSAGE_TYPE',
219+
data: { ... }
220+
});
221+
222+
// Handle in background
223+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
224+
if (message.type === 'MESSAGE_TYPE') {
225+
// Handle
226+
sendResponse({ success: true });
227+
}
228+
return true; // Keep channel open for async
229+
});
230+
```
231+
232+
### Message Types
233+
234+
| Type | Direction | Purpose |
235+
|------|-----------|---------|
236+
| `OPEN_SIDE_PANEL` | Popup → Background | Open sidepanel |
237+
| `TOGGLE_DRAWING_MODE` | Background → Content | Toggle drawing |
238+
| `SAVE_DRAWING` | Content → Background | Save drawing |
239+
| `GET_DRAWING` | Content → Background | Load drawing |
240+
| `CREATE_ANNOTATION` | Content → Background | Create annotation |
241+
| `GET_ANNOTATIONS` | Background → Content | Load annotations |
242+
| `HIGHLIGHT_ANNOTATION` | Sidepanel → Content | Highlight text |
243+
244+
## Build System
245+
246+
Built with Vite:
247+
248+
```
249+
src/ → dist/
250+
├── background/ → ├── background.js
251+
├── content/ → ├── content.js
252+
├── popup/ → ├── popup.html
253+
│ └── main.tsx → └── assets/popup-*.js
254+
├── sidepanel/ → ├── sidepanel.html
255+
│ └── main.tsx → └── assets/sidepanel-*.js
256+
└── utils/ → └── assets/*.js (shared chunks)
257+
```
258+
259+
## Security Considerations
260+
261+
1. **Auth tokens** encrypted with client secret
262+
2. **URLs hashed** for privacy in tags
263+
3. **Service worker isolation** prevents DOM access
264+
4. **Content Security Policy** in manifest
265+
5. **Local-first storage** - data stays local unless synced
266+
267+
## See Also
268+
269+
- [FEATURES.md](../FEATURES.md) - Feature documentation
270+
- [Testing Documentation](TESTING.md)
271+
- [UTF-16 Encoding](UTF16_HASH_ENCODING.md)
272+

0 commit comments

Comments
 (0)