2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00
2026-04-25 23:58:58 +03:00

Source Presences

Public registry of Source Presence extensions, served from gits.hibna.com.tr/hibna/source-presences.

The Source Presence browser extension reads:

  • index.json — list of presences and their current versions.
  • presences/<id>/metadata.json — presence manifest.
  • presences/<id>/dist/presence.js — built CJS module (produced by npm run build).
  • presences/<id>/<icon> — optional 128×128 PNG.

Both index.json and each presence's dist/presence.js are committed by the Gitea Actions workflow at .gitea/workflows/build.yml on every push to main.

Add a new presence

mkdir -p presences/<id>/src
cat > presences/<id>/metadata.json <<'JSON'
{
  "id": "<id>",
  "name": "<Display Name>",
  "description": "<short description>",
  "version": "1.0.0",
  "author": "<your name>",
  "match": ["https://example.com/*"],
  "tickInterval": 1000,
  "sdkVersion": "^0.1.0"
}
JSON

Write your TypeScript entry at presences/<id>/src/presence.ts:

import { ActivityType, definePresence } from "@source/presence-sdk";

export default definePresence({
  match: ["https://example.com/*"],
  tick(ctx) {
    ctx.setActivity({
      type: ActivityType.WATCHING,
      name: "Example",
      details: document.title,
    });
  },
});

Push to main. Gitea Actions builds the presence, regenerates index.json, and commits the artifacts back. The extension picks up the new version on its next 6-hour refresh, or immediately when users hit "Refresh" / "Update all".

Local build

npm install
npm run build     # builds every presence under presences/*
npm run index     # regenerates index.json
npm run release   # both

Presence API

PresenceDefinition shape (also defined in types/presence-sdk.d.ts):

Field Required Description
match yes Array of match patterns.
tickInterval no Override default 1000ms tick.
onLoad(ctx) no Runs once when a matching tab loads the presence.
tick(ctx) no Runs every tickInterval; call ctx.setActivity(...) to publish.
onUnload(ctx) no Runs when the presence is torn down (tab nav / disable).

PresenceContext:

  • ctx.url / ctx.tabActive — read-only state.
  • ctx.setActivity(activity) / ctx.clear() — publish or clear.
  • ctx.storage — namespaced async storage (get / set / delete / clear).
  • ctx.log / warn / error — surfaced in the extension's background console.

Activity payload

{
  type: ActivityType.PLAYING | LISTENING | WATCHING,
  name: string,
  details?: string,
  state?: string,
  url?: string,
  largeImage?: string,
  largeText?: string,
  smallImage?: string,
  smallText?: string,
  startedAt?: number,   // unix ms — Source renders an elapsed timer
  endsAt?: number,      // unix ms — Source renders a remaining timer
}

Notes

  • Presences run in the content script's isolated world with full DOM read access. They cannot access page JS globals.
  • The extension debounces identical payloads; calling setActivity with the same data on every tick is fine.
  • Keep presence builds small (< 100 KB). They're shipped with every install.
S
Description
No description provided
Readme 47 KiB
Languages
TypeScript 70.5%
JavaScript 29.5%