Claude-skill-registry custom-global-events
Guidelines for creating/using the app’s typed global events system.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/custom-global-events" ~/.claude/skills/majiayu000-claude-skill-registry-custom-global-events && rm -rf "$T"
skills/data/custom-global-events/SKILL.mdOverview
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 and is built on a typed
Event subclass (XCustomEvent).
It exposes:
: the canonical type map of event keys →global_event_Event
payload typesdetail
: dispatch a typed event (works outside React)global_event_dispatch(event, payload)
: listen with typed handler (works outside React)global_event_listen(event, handler, options?)
: React hook for subscriptions with stale-closure protectionuseGlobalEvent(event, handler)
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.
Example:
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):
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.
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):
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:
useGlobalEvent("ai_chat::open_canvas", (e) => { const payload = e.detail; });
Files and references
- Core implementation: global-event.tsx
- Typed event base:
in utils.tsXCustomEvent - Hook helper:
in utils-hooks.tsuseLiveRef - Example consumers: app-ai-chat.tsx, canvas.tsx