Skip to content

registerRecentsSource

registerRecentsSource feeds the Start menu’s Recent section, the Windows 11 region that lists recently used apps and recently used files. The apps half comes from the window manager’s own recency; sources contribute the files half: notes, documents, downloads, presets, whatever your apps touch and persist. Only the "menu" launcher (the Windows Start menu) renders the section; in the other launchers a registered source is simply never queried.

import { registerRecentsSource } from "@react-ui-os/desktop";
import type { RecentsSource, RecentItem } from "@react-ui-os/desktop";
function registerRecentsSource(id: string, source: RecentsSource): () => void;

A recents source returns its current items each time the Start menu opens. Read your own store inside the function so the rows are always fresh; the registry never caches results.

type RecentsSource = () => RecentItem[]
FieldTypeDescription
idstringStable id within the source; the menu keys rows by source id plus this.
namestringVisible row label, e.g. the document title.
timestampnumberEpoch ms of last use. The section orders newest first.
kindLabel?stringType label under the name ("Note", "Download").
accent?stringAccent color tinting the row's tile gradient.
icon?ReactNodeOptional icon node rendered inside the tile.
onActivate() => voidWhat to do when the row is activated (Enter or click).

id is a stable key: registering twice with the same id replaces the previous source, so it is safe to call from a component that re-mounts. The returned function unregisters the source; call it in the cleanup of the useEffect that registered.

The section holds six slots in a two-column grid, the Windows Recommended layout. Recently used apps lead; source items fill the remaining slots, newest timestamp first across all sources. Each row shows the icon (or the name’s first letter) on an accent tile, the name, and a subtitle built from kindLabel plus a relative time (“Note · 2h ago”).

useEffect(() => {
return registerRecentsSource("notes", () =>
listNotes(storage)
.slice(0, 4)
.map((note) => ({
id: note.id,
name: noteTitle(note) || "New Note",
timestamp: note.updatedAt,
kindLabel: "Note",
accent: "#f59e0b",
onActivate: () => openWindow({ kind: "app", appId: "notes" }),
})),
);
}, [storage, openWindow]);

Read your own store inside the source function: it is queried fresh each time the Start menu opens, never cached.

A throwing source is dropped for that call instead of taking down the Start menu, the same guard Spotlight sources get. Errors are logged to the console in development.