Skip to content

Contributing

Monorepo structure. Conventional commits. Local-first ethos.

loci is open source. Contributions welcome.


Repository structure

Loci/
├── packages/
│   ├── extension/          # Chrome MV3 extension (Vite + TypeScript)
│   ├── desktop/            # Tauri v2 desktop app (Rust + WebView)
│   └── server/             # MCP server (Rust)
├── docs/                   # VitePress documentation (you are here)
├── landing/                # loci.garden landing page
└── package.json            # Root workspace config

Each package has its own package.json (for JS) or Cargo.toml (for Rust).


Development setup

Extension

bash
cd packages/extension
npm install
npm run dev          # Watch mode with hot reload

Load the extension in Chrome:

  1. chrome://extensions > Enable Developer Mode
  2. Load unpacked > select packages/extension/dist/

The extension reloads automatically on file changes.

Desktop app

bash
cd packages/desktop
npm install
npm run tauri dev    # Runs Tauri in dev mode

Requires Rust toolchain. See Tauri prerequisites.

MCP server

bash
cd packages/server
cargo run            # Runs on localhost:3721

Docs

bash
cd docs
npm install
npm run dev          # VitePress dev server

Adding a new platform

To add support for a new AI chat platform (e.g., Gemini):

  1. Add selectors to packages/extension/src/platforms/platforms.config.ts:
typescript
export const platforms = {
  // ...existing
  gemini: {
    hostPatterns: ["gemini.google.com"],
    containerSelector: "[data-message-id]",
    userSelector: "[data-author='user']",
    assistantSelector: "[data-author='model']",
  },
};
  1. Create content script at packages/extension/src/content/gemini.ts:
typescript
import { attachObserver } from "./observer";
import { platforms } from "../platforms/platforms.config";

attachObserver(platforms.gemini);
  1. Register in manifest at packages/extension/manifest.json:
json
{
  "content_scripts": [
    {
      "matches": ["*://gemini.google.com/*"],
      "js": ["src/content/gemini.ts"]
    }
  ]
}
  1. Test on the live site. Verify MutationObserver captures turns correctly.

  2. Update docs: add the platform to the supported platforms table in /docs/extension/index.md.


Commit format

Use Conventional Commits:

<type>(<scope>): <description>

[optional body]

Types:

TypeUse for
featNew feature
fixBug fix
docsDocumentation only
refactorCode change that neither fixes a bug nor adds a feature
testAdding or updating tests
choreBuild process, dependencies, tooling

Scopes:

ScopePackage
extensionBrowser extension
desktopTauri app
serverMCP server
docsDocumentation
landingLanding page

Examples:

feat(extension): add Gemini platform support
fix(server): handle empty room context gracefully
docs: add MCP API reference
chore(extension): upgrade MiniSearch to 7.1.0

Pull requests

  1. Fork the repo
  2. Create a feature branch (git checkout -b feat/gemini-support)
  3. Make your changes
  4. Run tests (npm test in relevant package)
  5. Commit with conventional commit format
  6. Push and open a PR against main

PRs require one approval before merge.


Issue labels

LabelMeaning
bugSomething is broken
featureNew functionality request
docsDocumentation improvement
good-first-issueSuitable for new contributors
platformNew platform support request
securitySecurity-related (handled privately)

Code style

  • TypeScript: Strict mode, no any unless unavoidable
  • Rust: cargo fmt and cargo clippy clean
  • Naming: camelCase for JS, snake_case for Rust

No linter wars. Match the existing code.


Questions

Open a GitHub Discussion or reach out at hux@nymtech.net.

Built by Hux × Vesper · Apache 2.0