# Custom Global Events

> Guidelines for creating/using the app’s typed global events system.

- Skill: `majiayu000/custom-global-events` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/custom-global-events`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/custom-global-events/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/custom-global-events

---


# Overview

Global events are used for cross-component communication without React context dependencies, allowing for simple function calls to trigger events across different parts of the application.

# Global Events Guidelines

Global events are used for cross-component communication without React context dependencies, allowing for simple function calls to trigger events across different parts of the application.

# Overview

The global events system lives at [global-event.tsx](../../../packages/app/src/lib/global-event.tsx) and is built on a typed `Event` subclass (`XCustomEvent`).

It exposes:

- `global_event_Event`: the canonical type map of event keys → `detail` payload types
- `global_event_dispatch(event, payload)`: dispatch a typed event (works outside React)
- `global_event_listen(event, handler, options?)`: listen with typed handler (works outside React)
- `useGlobalEvent(event, handler)`: React hook for subscriptions with stale-closure protection

# Event key naming

Event keys are string literals using the pattern:

(`module::event_name`), for example `ai_chat::open_canvas`.

# How to add or modify an event

When the user requests a new global event, you must:

# Update the event map

Add the new event key to the `global_event_Event` map in [global-event.tsx](../../../packages/app/src/lib/global-event.tsx).

Example:

```ts
export class global_event_Event extends XCustomEvent<{
	"ai_chat::open_canvas": {
		pageId: app_convex_Id<"pages">;
		mode: "diff" | "editor";
		modifiedContent?: string;
		threadId: string;
	};
	"ai_chat::open_canvas_by_path": {
		path: string;
	};
	"docs::focus_path": {
		path: string;
	};
}> {}
```

# Keep all event keys centralized

All supported global event keys must be declared in that `global_event_Event` type map. Do not introduce ad-hoc stringly-typed events elsewhere.

# Use the exported helpers

Prefer `global_event_dispatch` / `global_event_listen` / `useGlobalEvent` rather than calling `window.dispatchEvent(new CustomEvent(...))` directly.

# Usage patterns

## React components

Use `useGlobalEvent(eventName, handler)` to subscribe. The handler receives a typed event object, and the payload is on `event.detail`.

Example (from [canvas.tsx](../../../packages/app/src/components/canvas/canvas.tsx)):

```ts
useGlobalEvent("ai_chat::open_canvas", (e) => {
	const payload = e.detail;
	// payload.pageId, payload.mode, payload.modifiedContent, payload.threadId
});
```

## Non-React code (or manual lifecycle control)

Use `global_event_listen` directly when you need to wire AbortController, or you are outside React.

```ts
const controller = new AbortController();

const cleanup = global_event_listen(
	"ai_chat::open_canvas_by_path",
	(e) => {
		console.info("path:", e.detail.path);
	},
	{ signal: controller.signal },
);

// later:
controller.abort();
cleanup();
```

## Dispatching

Use `global_event_dispatch(eventName, payload)` from anywhere client-side.

Example (from [app-ai-chat.tsx](../../../packages/app/src/components/app-ai-chat.tsx)):

```ts
global_event_dispatch("ai_chat::open_canvas_by_path", { path: args.path });
```

# Handler typing and payload access

Handlers receive the typed event object, not the payload directly:

```ts
useGlobalEvent("ai_chat::open_canvas", (e) => {
	const payload = e.detail;
});
```

# Files and references

- Core implementation: [global-event.tsx](../../../packages/app/src/lib/global-event.tsx)
- Typed event base: `XCustomEvent` in [utils.ts](../../../packages/app/src/lib/utils.ts)
- Hook helper: `useLiveRef` in [utils-hooks.ts](../../../packages/app/src/hooks/utils-hooks.ts)
- Example consumers: [app-ai-chat.tsx](../../../packages/app/src/components/app-ai-chat.tsx), [canvas.tsx](../../../packages/app/src/components/canvas/canvas.tsx)

