# How Archify's Live Preview Mode Works with File Watching: A Deep Dive into Real-Time Development

> Explore Archify's live preview mode and file watching. Learn how instant HTML updates streamline your real-time development workflow with incremental rebuilds and WebSockets.

- Repository: [tt-a1i/archify](https://github.com/tt-a1i/archify)
- Tags: deep-dive
- Published: 2026-08-17

---

**Archify's live preview mode uses a file watcher, incremental rebuild pipeline, and WebSocket server to push HTML updates to the browser instantly when source files change.**

Archify, the lightweight static site generator in the `tt-a1i/archify` repository, ships with a built-in development server that eliminates the manual refresh cycle. When you run `npm run preview` or `archify preview`, the tool monitors your project's `src/` directory and surfaces changes in the browser within milliseconds — no configuration required.

## How the File Watcher Initializes

The live preview starts in `scripts/build-start.mjs`, where Archify creates a **chokidar** watcher to monitor the filesystem. Chokidar wraps Node's native `fs.watch` with cross-platform consistency and reliability.

The watcher targets:
- The `src/` directory by default
- Any additional folders specified in the `watch` configuration array

When a file change occurs, the watcher emits a `change` event with the affected file path:

```javascript
// scripts/build-start.mjs – file watcher setup
import { watch } from 'chokidar';

const watcher = watch('src/**/*', { ignoreInitial: true });

watcher.on('change', path => {
  console.log(`File changed: ${path}`);
  // debounced rebuild and WebSocket broadcast follow
});

```

The `ignoreInitial: true` option prevents unnecessary rebuilds when the server first starts — only subsequent changes trigger updates.

## Incremental Rebuild on File Changes

The watcher callback invokes Archify's **incremental rebuild** system. Rather than rebuilding the entire site, the pipeline re-renders only the changed file and its dependent pages using the same Markdown-to-HTML transformer employed for static generation.

A **debounce timeout** guards against excessive work during rapid file saves:

```javascript
// scripts/build-start.mjs – rebuild orchestration
import { rebuild } from './build.js';

// Inside the change handler:
rebuild(path);  // re-render changed file + dependencies

```

This selective rebuild keeps preview updates fast even for larger projects, as implemented in the `tt-a1i/archify` source code.

## Live Update via WebSocket to Browser

The final piece is **bidirectional communication** with the browser. The preview server initializes a WebSocket server using the `ws` package, then broadcasts a `reload` message to all connected clients:

```javascript
// scripts/build-start.mjs – WebSocket server
import { WebSocketServer } from 'ws';

const wss = new WebSocketServer({ server });

// Inside the change handler:
wss.clients.forEach(c => c.send('reload'));

```

### Client-Side Hot Replacement

Each preview page includes a client-side script that receives the `reload` signal. Rather than triggering a full page refresh, this script fetches the fresh HTML and **swaps the `<body>` element** — preserving scroll position and state where possible.

Find this logic in [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html):

```html
<!-- examples/web-app.html – live-update client -->
<script>
  const ws = new WebSocket('ws://localhost:3000');
  ws.onmessage = ev => {
    if (ev.data === 'reload') {
      fetch(location.href)
        .then(r => r.text())
        .then(html => {
          const parser = new DOMParser();
          const doc = parser.parseFromString(html, 'text/html');
          document.body.replaceWith(doc.body);
        });
    }
  };
</script>

```

This **DOM diffing approach** delivers a near-instant preview experience that feels like native hot module replacement.

## Key Files in the Live Preview Pipeline

| File | Purpose |
|------|---------|
| `scripts/build-start.mjs` | Orchestrates the preview server, chokidar watcher, WebSocket broadcast, and incremental rebuild |
| [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html) | Demonstrates the client-side WebSocket handler that updates the preview |
| [`examples/web-app-rendered.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app-rendered.html) | Serves as the rendered output target for the live-preview server |
| `scripts/run-tests.mjs` | Reuses the watcher infrastructure for integration test automation |

## Configuring Watch Directories

By default, Archify watches `src/**/*`. Override this by adding a `watch` array to your project configuration:

```javascript
// archify.config.js
export default {
  watch: ['src/**/*', 'content/**/*', 'templates/**/*']
};

```

Paths are processed as glob patterns through chokidar, supporting exclusion patterns with `!` prefixes if needed.

## Summary

- **File watching** uses chokidar in `scripts/build-start.mjs` to monitor the `src/` directory and emit change events
- **Incremental rebuild** re-renders only affected files through a debounced `rebuild()` call
- **WebSocket broadcast** pushes `reload` messages to all connected browsers via the `ws` package
- **DOM hot-swap** in [`examples/web-app.html`](https://github.com/tt-a1i/archify/blob/main/examples/web-app.html) replaces the `<body>` without full page refresh for instant feedback

## Frequently Asked Questions

### What triggers a live preview update in Archify?

Any file creation, modification, or deletion within the watched `src/` directory (or configured `watch` paths) triggers the update chain. The chokidar watcher emits a `change` event, which debounces into a rebuild and WebSocket broadcast to all connected browsers.

### Does Archify live preview support custom watch paths?

Yes. Add a `watch` array to your Archify configuration with glob patterns for additional directories. The watcher merges these with the default `src/**/*` pattern before monitoring begins.

### Why does Archify use WebSocket instead of Server-Sent Events?

The `ws` implementation in `scripts/build-start.mjs` provides bidirectional capability that Archify reserves for future features like browser-to-server logging or configuration override. For the current unidirectional reload signal, either technology would function equivalently.

### Can I disable the hot DOM replacement and force full page reload?

The preview server always sends the `reload` message; the client-side handler in the page template controls the update behavior. To force full refreshes, modify the `onmessage` handler in your local copy of the preview template to call `location.reload()` instead of the body replacement logic.