---
title: Architecture
description: How the published package, the internal @filedom/* packages, the reconciler, and the native runtime fit together.
---

filedom is one published package (`filedom`) that bundles a set of internal
`@filedom/*` workspace packages. It is easiest to read as a stack of layers,
from the React tree down to Finder.

## Layer map

```text
React app
  -> filedom            (public entry points: filedom, filedom/system, filedom/sound)
  -> @filedom/components (StageProvider, Stage, Sprite, Text, Score, overlays, hooks, layout)
  -> @filedom/reconciler (React tree -> filesystem + Finder operations)
  -> @filedom/host       (TypeScript bridge to the Swift binaries)
  -> Swift controllers   (IconController, InputListener, AudioController)
  -> Finder / desktop state
```

`@filedom/types` is the shared contract underneath all of them. `@filedom/assets`
bakes icons and text, `@filedom/file-pool` recycles file handles for the Stage,
`@filedom/bridge` owns filesystem operations and the Desktop hide journal, and
`@filedom/sound` adds game audio on top of the host's audio primitives.

## Responsibilities

### Public entry points: `filedom`

The published package re-exports the public surface through three entry points:
`filedom` (reconciler, components, hooks, assets, and game controls),
`filedom/system` (host bridge and filesystem), and `filedom/sound` (audio). In
the monorepo these resolve to TypeScript source, so apps track the live API
without a build step; `publishConfig` swaps them to the bundled `dist` at pack
time.

### Shared types: `@filedom/types`

Defines the virtual desktop model: node types for files, folders, and desktop
roots, the icon and background descriptors, `SystemMetrics`, and enums such as
`VirtualNodeType`, `IconColor`, and `ViewOptionsArrangement`. Every other
package depends on this contract.

### Components and hooks: `@filedom/components`

The renderable building blocks: `Wallpaper`, the `Stage`/`Sprite`/`Score`/`Text`
and overlay system, layout helpers (`createGrid`, `distribute`), and hooks
(`useBounds`, `useViewOptions`, `useDesktopDrag`, `useKeypress`, and others).
Components produce custom element types for the reconciler instead of DOM
nodes. The file and folder elements that `Stage` emits are internal to this
package and not exported.

### Reconciler: `@filedom/reconciler`

Turns React updates into desktop side effects: creating and deleting files and
folders, batching Finder mutations, applying icon positions and custom icons,
changing the wallpaper, and reading and restoring view options. `createRoot`,
`render`, and the `startSession` lifecycle live here.

### Host bridge: `@filedom/host`

The macOS integration layer. It exposes TypeScript functions for Finder
operations and hands native work to the Swift binaries: long-lived Finder
control through `IconController`, keyboard and mouse capture through
`InputListener`, and audio through `AudioController`.

### Filesystem bridge: `@filedom/bridge`

Filesystem operations and file ownership are kept apart from Finder automation.
The Desktop hide journal is a TypeScript state machine that drives a
filesystem-only `StashController` helper. The helper holds an advisory lock on
the Desktop, publishes synced journals atomically, and sets or clears
`UF_HIDDEN` through a descriptor opened relative to the locked directory,
re-checking the inode's identity on that descriptor before the flag changes.
Files are never moved, so nothing can collide or be overwritten, and the helper
never starts Finder or input services. Recovery validates identities and stops
on anything ambiguous. A journal in the old move format also stops recovery and
is left for inspection.

## Why this split exists

A React commit requests work; Finder may not have applied it yet. The reconciler
coalesces positions per file and waits for file creation and icon preparation.
Stage starts its paint allowance only after the native unhide is confirmed.

Stacking repairs wait for revocable placement acknowledgements through a
host-installed driver. They work on connected groups of overlapping sprites
within one Stage, validate the exact selection and native targets, and track
gesture cleanup through shutdown. A component whose repair failed and has not
changed stays suppressed on its own, without affecting others. A posted gesture
updates a ledger of the believed order; Finder offers no z-order readback.

Each root has one exclusive `RendererRuntime`. It owns the position and
visibility queues, Finder batches, the serialized filesystem lane, the async and
native-gesture ledgers, expected-position baselines, and wallpaper and view
state. `root.dispose()` drains that runtime and unregisters its drivers;
`session.close()` also restores session resources without exiting the process.
Late async work stays with the root that started it and never passes to a later
root.

Cleanup failures are still reported at disposal after their tasks settle.
Ordinary interrupted repairs and recoverable live updates are tracked
separately and do not fail cleanup. The native daemon, input services, name
registries, and durable caches are shared across roots. Only one root or session
can be active at a time, so FileDOM does not run concurrent Finder sessions.
Explicit ordering across Stages, beyond creation order and user drags, is open
work listed in the
[repository status notes](https://github.com/methodacting/filedom/blob/main/docs/current-status.md).

Keeping the layers separate lets each one be documented from two sides: how to
use it from React, and how it works underneath. This page connects the two.
