Skip to content

TypeScript SDK ​

The glimpse-sdk package exports React components, hooks, host requests, and supporting types for exec applets. Configure TypeScript with "jsx": "react-jsx" and "jsxImportSource": "glimpse-sdk".

Create an applet

sh
glimpsectl applet new --language ts --id me.aresa.GlimpseTodo --yes
cd glimpse-todo
just dev

The todo tutorial builds a full applet from this project. just lint checks the code with Biome, which the project's npm install brings; its site has the editor extension and a standalone install.

Components ​

Every component is imported from glimpse-sdk and documented, with its props and TypeScript usage, in Elements. React.ComponentProps<typeof Indicator> gives a component's props type.

Hooks ​

ts
function useState<T>(initial: T | (() => T)): [T, (action: T | ((prev: T) => T)) => void];
function useEffect(effect: () => void | (() => void), deps?: readonly unknown[]): void;
function useOptions<T extends Record<string, unknown> = Record<string, unknown>>(): T;
function usePlacement(): Placement | null;
function usePopover(): { open: boolean; close: () => void };
function useAppletName(): string;
function useStateDir(): string;
function usePersistentState<T>(key: string, initial: T): [T, (action: T | ((prev: T) => T)) => void];
  • useState and useEffect are React's.
  • useOptions returns the current options. The type parameter is a cast, not validation.
  • usePlacement returns null until the panel sends the placement.
  • usePopover tells whether the popover is open, and close closes it. close is the same function on every render.
  • useAppletName returns this configured instance's name.
  • useStateDir returns the applet's own directory for files, created with mode 0700.
  • usePersistentState works like useState and saves key to state.json in that directory. It loads the saved value on the first render; a missing or unreadable file gives initial. Several keys share one file.

Desktop actions ​

ts
function notify(message: {
  summary: string;
  body?: string;
  icon?: string;
  urgency?: "low" | "normal" | "critical";
}): void;
function copy(text: string): void;
function openUri(uri: string): void;
function launch(id: string): void;

notify defaults to an empty body and normal urgency. It runs notify-send from the applet process and copy runs wl-copy, so libnotify and wl-clipboard must be installed; the notification daemon applies its own limits. launch takes an installed desktop-file id with or without .desktop. openUri accepts only http, https, mailto, and eligible file URIs, at most 2,048 bytes. See Notify, copy, open links and launch apps for file restrictions.

Runtime and JSX exports ​

ts
function run(element: unknown, io?: Io): Promise<void>;
function createElement(
  type: unknown,
  props?: Record<string, unknown> | null,
  ...children: unknown[]
): unknown;
const Fragment: typeof React.Fragment;
function jsx(type: unknown, props: unknown, key?: unknown): unknown;
function jsxs(type: unknown, props: unknown, key?: unknown): unknown;
function jsxDEV(type: unknown, props: unknown, key?: unknown): unknown;

interface Io {
  writeLine: (line: string) => void;
  lines: AsyncIterable<string | string[]>;
}

interface Placement {
  output: string | null;
  position: string;
  orientation: string;
  zone: string;
  size: number;
}

type Node =
  | string | number | boolean | null | undefined | Node[]
  | { type: unknown; props: unknown; key: unknown };

type FC<P = object> = (props: P & { key?: string | number }) => Node;

run connects to the socket named by GLIMPSE_APPLET_SOCKET. Without that variable and without an io, it prints GLIMPSE_APPLET_SOCKET is not set: run the applet under the panel and exits 1. A supplied Io replaces the socket. run redirects console methods to stderr and exits 0 when the session ends. jsx, jsxs and jsxDEV are what the JSX runtime calls; you never call them.

The host's placement values are top, bottom, left, or right for position; horizontal or vertical for orientation; and left, center, or right for zone. size is the bar's logical-pixel thickness, and output is its connector name or null.

The separate glimpse-sdk/testing entry point exports render and the Rendered type. See Test an applet for its methods.

Released under the BSD 3-Clause license.