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

├── manifests/                   # Browser extension manifests
│   ├── base.json                # Shared fields (merged into every browser manifest)
│   ├── chrome/manifest.json     # Chrome-specific overrides
│   ├── firefox/manifest.json    # Firefox-specific overrides (gecko id, strict_min_version)
│   └── safari/manifest.json     # Safari-specific overrides

├── packages/                    # Internal workspace packages (if any)

├── scripts/                     # Build-time scripts
│   ├── build.ts                 # Main build orchestrator
│   ├── clean.ts                 # Removes dist/
│   ├── merge-manifest.ts        # Merges base.json + browser overlay → dist/<browser>/manifest.json
│   └── prepare-generated-lexicons.ts  # Processes lexicon JSON for use at runtime

├── src/                         # Extension source
│   ├── background/
│   │   ├── service-worker.ts    # Entry point for background context; registers message router
│   │   └── message-router.ts    # Routes incoming browser.runtime messages to handlers
│   │
│   ├── content/
│   │   ├── content-script.ts    # Entry point injected into bsky.app pages
│   │   ├── post-detector.ts     # DOM scanning: finds posts authored by you; 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           # Extension content 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
│   │
│   ├── options/                 # Extension options page (currently minimal)
│   │   ├── options.html
│   │   ├── options.ts
│   │   └── options.css
│   │
│   ├── platform/                # Per-browser API shims
│   │   ├── chrome/              # Chrome-specific shim
│   │   ├── firefox/             # Firefox-specific shim
│   │   └── safari/              # Safari-specific shim
│   │
│   ├── popup/                   # Toolbar popup UI
│   │   ├── popup.html
│   │   ├── popup.ts             # Popup entry point; imports auth-popup Web Component
│   │   ├── auth-popup.ts        # <auth-popup> Web Component: sign in / out / status
│   │   └── popup.css
│   │
│   └── shared/                  # Code shared across all extension contexts
│       ├── constants.ts         # APP_NAME, BSKY origins, OAuth endpoints/scopes
│       ├── 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 # SessionStore: read/write/clear tokens in browser.storage.local
│       │   ├── token-refresh.ts # TokenRefreshManager: deduplication, proactive refresh
│       │   └── types.ts         # OAuthTokens, Session, AuthStatus types
│       └── utils/
│           ├── facet-offsets.ts # UTF-8 byte offset helpers
│           ├── 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
│   │
│   ├── 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/

├── package.json                 # Root workspace package (scripts, devDependencies)
├── pnpm-workspace.yaml          # pnpm monorepo workspace definition
├── turbo.json                   # Turborepo pipeline (build, test, lint)
├── tsconfig.json                # Root TypeScript config (paths, strict)
├── tsconfig.build.json          # TypeScript config for production builds (excludes test/)
├── vite.config.ts               # Vite config (entry points, resolve aliases)
├── 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/*"] }
  • vite.config.tsresolve.alias: { "@src": "src/" }
  • 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.