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 aRendererRoot. Call it with no argument to render to the real~/Desktop, with a path string to target another directory, or with a fullVirtualDesktopcontainer. 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 standardVirtualDesktopcontainer for a path (default~/Desktop), the same objectcreateRoot()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?)startsdispose()and callscallbackwhen it finishes.prepared,desktopPrepared,poolPrepared, andreadyare 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:
- reserves the desktop, rejecting a second root or session before any change;
- installs
SIGINT,SIGTERM, andSIGHUPhandlers that run the cleanup; - autohides the Dock and menu bar, recording the user’s own settings first;
- shows the optional controls dialog;
- hides the user’s existing Desktop items in place (see below);
- 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: theRendererRoot.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 yourcleanup, 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 anAggregateError. After a failed close the session keeps ownership of the desktop, so restart the process instead of reusing it.exit(): runsclose(), 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 (defaulttrue).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, orfalsefor 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:
- Wallpaper and VirtualTreeProvider
- Stage & Sprite:
StageProvider,Stage,Sprite, and the park hooks (useStagePark,useStageSession,canonicalPark) - Text & scores:
ScoreandText, the single text component, whichtextTilesfeeds - Overlay & controls:
useGameControls,useGameOverlay,GameOverlay - Layout:
fitIconSize,centerBoard,createGrid,distribute - Hooks: metrics, view options, input, game loop
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, andRETRO_FONT_FILE(the shared arcade face). - Glyphs and digits:
glyphIcon,boxedGlyphIcon(the banner sets),scoreDigitIcon,resolveDigitIcon. - Rasterizing:
rasterizeSvg,sliceSvgGrid,bakeIconPng, andbakeIconPngSync. 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.
Related
filedom/system: the native and filesystem bridgefiledom/sound: game audio- Architecture: how the packages fit together