Skip to content

Project Structure

text
skeeditor/
├── docs/                        # VitePress documentation site
│   ├── .vitepress/
│   │   └── config.ts            # VitePress site configuration
│   ├── guide/                   # User-facing documentation
│   └── dev/                     # Developer documentation

├── lexicons/                    # AT Protocol Lexicon JSON files
│   ├── app/bsky/                # Bluesky app lexicons
│   └── com/atproto/             # Core AT Protocol lexicons

├── packages/                    # Internal workspace packages
│   └── labeler/                 # Cloudflare Worker — skeeditor labeler service
│       ├── package.json
│       ├── tsconfig.json
│       ├── wrangler.jsonc       # Cloudflare Worker config (routes, bindings, vars)
│       └── src/
│           ├── index.ts         # Worker entry point (fetch handler)
│           ├── auth.ts          # DID authentication helpers
│           ├── hub.ts           # BroadcastHub Durable Object (subscription state)
│           ├── label.ts         # Label creation / signing logic
│           ├── did-document.ts  # DID document resolver
│           └── types.ts         # Shared types for the labeler worker

├── scripts/                     # Build-time scripts
│   ├── merge-manifest.ts        # Merges manifest overlays (legacy; not used by main WXT build)
│   └── prepare-generated-lexicons.ts  # Processes lexicon JSON for runtime use

├── src/                         # Extension source
│   ├── assets/
│   │   └── icon.svg             # Source icon — auto-icons generates PNGs from this
│   │
│   ├── background/
│   │   └── message-router.ts    # Routes incoming browser.runtime messages to handlers
│   │
│   ├── entrypoints/             # WXT entrypoints (discovered automatically by WXT)
│   │   ├── background.ts        # Background service worker entry point
│   │   ├── content.ts           # Content script entry point (injected into bsky.app)
│   │   ├── popup/
│   │   │   ├── index.html       # Popup HTML shell
│   │   │   └── main.ts          # Popup entry point — mounts the auth-popup component
│   │   └── options/
│   │       ├── index.html       # Options page HTML shell
│   │       └── main.ts          # Options page entry point
│   │
│   ├── content/
│   │   ├── post-detector.ts     # DOM scanning: finds your posts; extracts PostInfo
│   │   ├── post-badges.ts       # Injects Edit badge elements next to your posts
│   │   ├── post-editor.ts       # Orchestrates GET_RECORD → edit modal → PUT_RECORD
│   │   ├── edit-modal.ts        # In-page editor modal Web Component
│   │   └── styles.css           # Content-script styles
│   │
│   ├── lexicons/                # Generated TypeScript types from AT Protocol lexicons
│   │   ├── app.ts               # Re-exports from app/bsky.ts
│   │   ├── com.ts               # Re-exports from com/atproto.ts
│   │   └── tools.ts             # Re-exports from tools/ozone.ts
│   │
│   ├── platform/                # Per-browser API shims
│   │   ├── chrome/              # Chrome-specific shim
│   │   ├── firefox/             # Firefox-specific shim
│   │   └── safari/              # Safari-specific shim
│   │
│   ├── popup/
│   │   └── auth-popup.ts        # <auth-popup> Web Component: sign in/out, multi-account, status
│   │
│   └── shared/                  # Code shared across all extension contexts
│       ├── constants.ts         # APP_NAME, BSKY origins, OAuth endpoints, settings helpers
│       ├── messages.ts          # Typed message union + ResponseFor<T> + sendMessage()
│       ├── api/
│       │   ├── at-uri.ts        # AT-URI parser and builder (AtUri class)
│       │   └── xrpc-client.ts   # XrpcClient: getRecord, putRecord, putRecordWithSwap
│       ├── auth/
│       │   ├── auth-client.ts   # OAuth PKCE client (initiate flow, exchange code, revoke)
│       │   ├── pkce.ts          # generateCodeVerifier / generateCodeChallenge utilities
│       │   ├── session-store.ts # Multi-account session store; keyed by DID in browser.storage.local
│       │   ├── token-refresh.ts # TokenRefreshManager: deduplication, proactive refresh
│       │   └── types.ts         # OAuthTokens, Session, AuthStatus types
│       └── utils/
│           ├── facet-offsets.ts # Recalculate facet byte offsets after text edits
│           ├── facets.ts        # detectLinks / detectMentions / detectHashtags / buildFacets
│           └── text.ts          # Text-manipulation helpers (grapheme count, etc.)

├── test/
│   ├── e2e/                     # Playwright end-to-end tests
│   │   ├── chrome.spec.ts       # Chrome extension E2E
│   │   ├── firefox.spec.ts      # Firefox extension E2E
│   │   └── fixtures/            # Playwright fixture helpers + mock bsky page
│   │
│   ├── integration/             # Vitest integration tests (with MSW HTTP mocking)
│   │   ├── api/
│   │   ├── auth/
│   │   └── health.test.ts
│   │
│   ├── mocks/                   # Shared test mocks
│   │   ├── browser-apis.ts      # chrome/browser API stubs
│   │   ├── handlers.ts          # MSW request handlers (XRPC mock responses)
│   │   ├── server.ts            # MSW server setup
│   │   └── wxt-utils.ts         # Stubs for wxt/utils/* (not resolvable outside WXT pipeline)
│   │
│   ├── setup/
│   │   ├── unit.ts              # Vitest unit setup (registers browser-api mocks)
│   │   └── integration.ts       # Vitest integration setup (starts/stops MSW server)
│   │
│   └── unit/                    # Vitest unit tests (jsdom)
│       ├── api/
│       ├── auth/
│       ├── background/
│       ├── content/
│       └── utils/

├── .wxt/                        # Generated by WXT (type stubs, tsconfig patches)
│                                # Not committed; regenerated by `pnpm install`

├── package.json                 # Root workspace package (scripts, devDependencies)
├── pnpm-workspace.yaml          # pnpm monorepo workspace definition
├── tsconfig.json                # Root TypeScript config (paths, strict)
├── tsconfig.build.json          # TypeScript config for production builds (excludes test/)
├── wxt.config.ts                # WXT build config (manifest, entrypoints, browser targets)
├── vitest.config.ts             # Vitest config (unit + integration environments)
└── playwright.config.ts         # Playwright config (E2E)

Key path alias

All src/ imports use the @src alias, which maps to the src/ directory. This is configured in:

  • tsconfig.jsonpaths: { "@src/*": ["src/*"] }
  • wxt.config.tsresolve.alias: { "@src": "src/" } (passed into Vite)
  • vitest.config.ts — same alias for test imports

Example:

ts
import { sendMessage } from "@src/shared/messages";
import { XrpcClient } from "@src/shared/api/xrpc-client";

Released under the MIT License.