Widgets
Programmatic API

Programmatic API

Each widget exposes a small global on window so you can open drawers, read counts, or trigger refreshes from your own code — without re-implementing the UI.

Use this when:

  • You want a custom button somewhere on the page that opens the drawer (e.g. "Cart" link in a hamburger menu that should pop the same drawer as the bell).
  • You want to display the unread count somewhere outside the widget's own badge (e.g. in a sticky footer, in the page title).
  • You want to refresh the widget's state after a known event (e.g. after a custom checkout flow completes, refresh the cart).

All APIs are stable in v1 and safe to call before the widget has finished booting — calls before mount queue up and apply once ready. The globals only appear after the widget bundle has loaded though, so guard with optional chaining:

window.CobuntuCart?.open();

CobuntuAuth

Available after /widgets/v1/auth.js loads.

window.CobuntuAuth = {
  /** True if the visitor is authenticated. Reads the cobuntu_auth
   *  cookie + checks JWT expiry. Pure / synchronous. */
  isAuthenticated(): boolean;
 
  /** Open the profile drawer. If the visitor isn't authenticated,
   *  navigates to /login?next=<current path> instead. */
  openProfile(): void;
 
  /** Close the profile drawer if it's open. No-op otherwise. */
  closeProfile(): void;
 
  /** Sign the user out. Clears the cookie + reloads. */
  signOut(): void;
 
  /** Re-fetch the user's profile from /api/users/me. Useful after
   *  the user updates their avatar / name elsewhere. */
  refresh(): void;
};

CobuntuCart

Available after /widgets/v1/cart.js loads.

window.CobuntuCart = {
  /** Open the cart drawer. */
  open(): void;
  close(): void;
  /** Current cart item count (drives the badge). */
  count(): number;
  /** Re-fetch cart contents + remount the trigger. Call after a
   *  successful add-to-cart from your own UI. */
  refresh(): void;
};

CobuntuMessages

Available after /widgets/v1/messages.js loads.

window.CobuntuMessages = {
  /** Current unread message count. */
  unread(): number;
  /** Re-fetch the unread count. */
  refresh(): Promise<void>;
  /** Navigate to /conversations (or /login?next=/conversations
   *  if not authenticated). */
  open(): void;
};

CobuntuNotifications

Available after /widgets/v1/notifications.js loads.

window.CobuntuNotifications = {
  /** Current unread notification count. */
  unread(): number;
  /** Re-fetch the unread count. */
  refresh(): Promise<void>;
  /** Open the notifications drawer. (Navigates to /login?next=/hub
   *  if not authenticated.) */
  open(): void;
  /** Close the drawer if it's open. */
  close(): void;
};

CobuntuSearch

Available after /widgets/v1/search.js loads.

window.CobuntuSearch = {
  /** Open the search modal. */
  open(): void;
  close(): void;
};

Patterns

Custom trigger that opens an existing drawer

<!-- Your own button anywhere on the page -->
<button id="open-cart">My cart</button>
 
<script>
  document.getElementById("open-cart").addEventListener("click", () => {
    window.CobuntuCart?.open();
  });
</script>

Show unread count in the page title

function updateTitle() {
  const n =
    (window.CobuntuMessages?.unread() ?? 0) +
    (window.CobuntuNotifications?.unread() ?? 0);
  document.title = n > 0 ? `(${n}) ${baseTitle}` : baseTitle;
}
setInterval(updateTitle, 60_000);

Refresh after a server-side change

// After your own API call that affects the cart…
await fetch("/api/something");
window.CobuntuCart?.refresh();

What's NOT on the public API

These exist in the bundles but are NOT part of the stable contract and may change without a major version bump:

  • Internal cache structures (profilePromise, cartItems, notifications[], etc.).
  • Internal DOM selectors (.cobuntu-cart-drawer__row, etc.) — use CSS variables for styling overrides, don't tree-shake the markup.
  • The auto-theme <style id="cobuntu-community-theme-vars"> — read it as theming output, not an API.

If you need something here that isn't exposed, open an issue — we'll add it under the namespaced global rather than break v1.