Monorepo Architecture
Relevant source files
The following files were used as context for generating this wiki page:
Oddity 1 utilizes a monorepo structure to organize its Chrome extension, backend API, and shared utilities into a single repository. This architecture allows developers to install dependencies for all workspaces in a single step and ensures consistent type definitions across the frontend and backend.
The project splits functionality into three primary workspaces: a shared package for contracts, a browser extension for client-side interaction, and a Node.js backend for processing AI annotations.
Sources: README.md:3-15, CHANGELOG.md:88-103
Workspace Organization
The repository contains three core directories under the root, each serving a distinct role in the application lifecycle.
Core Workspaces
| Workspace Path | Name | Description |
|---|---|---|
packages/shared/ | @oddity/shared | Contains TypeScript types, constants, timing limits, and color definitions. |
extension/ | Chrome Extension | A Manifest V3 extension built with Vite and CRXJS. Handles DOM interaction and PDF export. |
backend/ | Express API | An API deployable to Vercel that manages LLM interactions, caching, and user profiles. |
Sources: README.md:5-15, CHANGELOG.md:88-103
Dependency Management
You install all workspace dependencies from the repository root using npm install. The extension build process reads environment variables from multiple levels, including the root, backend/.env, and extension-specific .env files.
Sources: README.md:27-30, README.md:61-63
Structural Overview
The following diagram illustrates the relationship between the monorepo components and external services.
The monorepo architecture ensures that both the Extension and Backend stay synchronized via the Shared package.
Sources: README.md:5-15, extension/src/background/index.ts:18-70
Client Architecture (Extension)
The extension/ workspace implements a multi-script architecture required by Chrome Manifest V3.
Service Worker (Background)
The background script acts as the central router for the extension. It manages authentication states, routes messages between content scripts and the backend, and handles site adapter registration. It also implements an optimization layer using AbortController to cancel in-flight requests when a user navigates or re-triggers an annotation.
Key responsibilities include:
- Concurrency Limiting: Restricts simultaneous API requests per tab to prevent rate limit bursts.
- PDF Detection: Monitors tab updates to programmatically inject scripts into PDF files.
- Auth Management: Handles Supabase auth sessions and Google OAuth tokens.
Sources: extension/src/background/index.ts:20-60, extension/src/background/index.ts:107-124
Content Script and PDF Engine
The content script performs smart text extraction using Mozilla's Readability or site-specific adapters. It handles the rendering of in-place overlays, margin notes, and popovers. The PDF export module replicates host-page content into a sanitized HTML document, injecting sidenotes in a Tufte-style float layout before triggering the print dialog.
Sources: extension/src/content/export-pdf.ts:60-100, CHANGELOG.md:105-112
Server Architecture (Backend)
The backend/ workspace provides the computational logic and storage interface for the application.
API and LLM Integration
The backend uses Express to handle requests for generating and fetching annotations. It interacts with OpenRouter for LLM streaming and utilizes Supabase for user profile management and caching.
- Annotation Cache: AI annotations are keyed by
(content_hash, intensity)with a 30-day TTL. - Prompt Management: System prompts are stored in
backend/config/prompts.json, supporting different "Personalities" (e.g., Terry, Jerry, Sally) and intensity levels.
Sources: backend/config/prompts.json:1-15, README.md:183-195, CHANGELOG.md:114-122
Data Communication Flow
The following sequence diagram represents the data flow when a user requests annotations for a web page.
The system prioritizes perceived speed by using a stale-while-revalidate strategy for cached annotations.
Sources: extension/src/background/index.ts:200-280, backend/lib/tests/openrouter.test.ts:110-150
Shared Package Definitions
The @oddity/shared package serves as the single source of truth for the monorepo.
- Types: Defines all TypeScript contracts, including
Annotation,ExtensionMessage, andUserPreferences. - Constants: Manages hardcoded values like
BACKEND_URL, rate limits, and timing thresholds. - Visuals: Defines annotation colors and labels used by both the rendering engine in the extension and the PDF export utility.
Sources: README.md:5-10, extension/src/content/export-pdf.ts:5-40
Conclusion
The Oddity 1 Monorepo Architecture provides a robust framework for coordinating a Chrome extension and a backend API. By centralizing types in a shared package and utilizing a sophisticated message routing system in the extension's service worker, the project maintains data integrity while optimizing for low-latency AI interactions. The structure supports complex features like streaming chatbot support and persistent manual annotations across multiple web environments.
Sources: README.md:5-15, CHANGELOG.md:88-122