Skip to content
filedom
Esc
↑↓navigate↵open⌘Jpreview
On this page

filedom

The main entry point: roots, the startSession lifecycle, the asset-authoring toolkit, and shared types.

The default entry point, filedom, has everything needed to build desktop apps and games. Components and hooks have their own pages. This page covers roots and the session lifecycle, asset authoring, and the shared types. Native and filesystem operations are in filedom/system.

Roots

import { createRoot, desktopContainer, render } from 'filedom';
import type { RendererRoot, VirtualDesktop } from 'filedom';
  • createRoot(container?) returns a RendererRoot. Call it with no argument to render to the real ~/Desktop, with a path string to target another directory, or with a full VirtualDesktop container. Only one root or session can be active at a time; creating a second one throws before it touches the desktop.
  • desktopContainer(path?) builds the standard VirtualDesktop container for a path (default ~/Desktop), the same object createRoot() uses.

A RendererRoot has these members:

  • render(element, callback?) renders or updates the tree.
  • await dispose() unmounts the tree, deletes the files it rendered, waits for queued native work, and restores any wallpaper or view options the tree changed. Repeated calls share one result, and cleanup failures reject it.
  • unmount(callback?) starts dispose() and calls callback when it finishes.
  • prepared, desktopPrepared, poolPrepared, and ready are promises for the startup stages: the boot sweep of a previous run’s leftover files, the initial wallpaper and view options, a warm Stage pool, and the initial presentation.

startSession

Use startSession for a full desktop takeover instead of wiring the steps yourself:

import { startSession } from 'filedom';

const session = await startSession(<MyGame />, {
  dialog: { title: 'My Game', message: 'Arrows move · Q quits' },
});
// session.exit(): unmount, clean up, restore the desktop, exit the process.

In order, startSession:

  1. reserves the desktop, rejecting a second root or session before any change;
  2. installs SIGINT, SIGTERM, and SIGHUP handlers that run the cleanup;
  3. autohides the Dock and menu bar, recording the user’s own settings first;
  4. shows the optional controls dialog;
  5. hides the user’s existing Desktop items in place (see below);
  6. creates the root, waits for calibrated metrics, renders, and shows the desktop.

With the default clearDesktop: true, the Desktop items are hidden by setting the macOS hidden flag on them. Their files are not moved, renamed, or deleted, and their icon positions survive. A journal at ~/.filedom-desktop-stash records each item’s identity before any flag changes. A journal left by a crashed run is recovered on the next start, and ambiguous recovery stops for inspection. On exit, the flag is cleared only where the file is still the same inode and still hidden, so items the user had already hidden stay hidden. Finder’s “show all files” preference is turned off for the session with Cmd+Shift+. (this needs Accessibility) and restored afterwards. See Desktop stash & restore.

startSession returns a DesktopSession:

  • root: the RendererRoot.
  • ready: resolves when the initial presentation is complete and rejects on a startup failure.
  • close(): restores everything without exiting the process. It removes the game’s files, runs your cleanup, reveals the Desktop items, and puts the Dock and menu bar back. Repeated calls share one result. Every step is attempted, and failures reject together as an AggregateError. After a failed close the session keeps ownership of the desktop, so restart the process instead of reusing it.
  • exit(): runs close(), then exits the process.

A startup failure rolls back through the same cleanup, so a cleanup hook must tolerate a partial start.

StartSessionOptions:

  • dialog: { title, message } for the controls dialog.
  • clearDesktop: hide the user’s Desktop items for the session (default true).
  • cleanup: an async hook that runs during close or startup rollback, before hidden items are revealed.
  • desktopPath: the directory to render into (default ~/Desktop).
  • feedback: a lifecycle status display, or false for none.

cleanup is rarely needed. The library owns every filename a Stage mints: unmount removes the files it rendered, and leftovers from a run that exited uncleanly are swept at the next boot. Use cleanup for desktop files your own code created outside the reconciler.

Under Finder Mode (FINDER_MODE_SUPERVISED), the signed app hides and restores the Desktop itself, using its own journal at ~/.finder-mode-stash, and shows its own controls UI. The session skips its own hiding and the dialog.

Components, hooks, stages

Everything on these pages is exported from filedom:

Asset-authoring toolkit

Icons are pre-baked PNGs, because the rendering model rules out changing them at runtime, so every game has an asset build step. The toolkit makes one manifest the source of truth for both the build and the runtime:

import path from 'node:path';
import { defineAssets, solid, type IconSpec } from 'filedom';

const ball: IconSpec = (c) => c.circle({ r: c.canvas * 0.4, fill: '#f5f5f4' });

export const assets = defineAssets({
  iconDir: path.resolve(import.meta.dirname, 'assets/icons'),
  icons: {
    ball,
    paddle: solid('#38bdf8'),
  },
});

// build step: `assets.build()` renders SVG → PNG into iconDir (sync)
// runtime:    `assets.icon('ball')` → IconDescriptor, `assets.iconPath('ball')`

An icon entry is either an IconSpec draw function, (c: DrawContext) => svg-fragment, or { svg: () => string, size? } for a complete SVG document. The manifest has icon(key), iconPath(key), build(), and iconKeys. Keys are typed, so a misspelled asset name fails at compile time. textStrip returns { count, tiles }; spread its tiles into icons under your own keys, one per tile.

All of these are exported from filedom:

  • Manifest: defineAssets, DrawContext, solid, playButton, lighten, ICON_CANVAS_SIZE, ICON_PAINTED_FRACTION, tileStride.
  • Typography: textTiles (lines and a shape in, a laid-out block for Text out), stripTiles (the same layout for tiles you baked yourself), renderText, labelIcon, textStrip (one kerned line sliced across several tiles), textCells (the dense monospace grid), textTileStride, loadFont, defaultFontFile, and RETRO_FONT_FILE (the shared arcade face).
  • Glyphs and digits: glyphIcon, boxedGlyphIcon (the banner sets), scoreDigitIcon, resolveDigitIcon.
  • Rasterizing: rasterizeSvg, sliceSvgGrid, bakeIconPng, and bakeIconPngSync. The bake functions cache by content hash across runs.

Shared types

The entry point re-exports every type from the types package, including VirtualDesktop, VirtualFile, VirtualFolder, VirtualNodeType, IconDescriptor and its IconSource variants, SystemMetrics, ViewOptionsProps, WallpaperProps, and PositionTransition. The IconColor and ViewOptionsArrangement enums are exported as values.

Was this page helpful?