🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@domstack/sync

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@domstack/sync

A modern, minimal live-reload dev server

latest
Source
npmnpm
Version
0.0.5
Version published
Weekly downloads
65
-66.84%
Maintainers
1
Weekly downloads
 
Created
Source

@domstack/sync

latest version Actions Status downloads neostandard javascript style Socket Badge

A modern, dependency-minimized live-reload dev server. A love letter to browser-sync: ESM-only, Fastify, native WebSocket, and a server-rendered HTMX UI panel.

Install

npm install @domstack/sync

CLI

# Serve current directory, watch CSS and HTML
domstack-sync --server . --files '**/*.css' '**/*.html'

# Serve current directory and watch the served root
domstack-sync --server . --watch

# Watch files without serving (snippet-injection mode)
domstack-sync --files '**/*.css'

# Short alias
dss --server . --files '**/*'

# Disable the UI panel
domstack-sync --server . --no-ui

# Write a starter ESM config file
domstack-sync init

# Trigger a reload from another terminal
domstack-sync reload --port 3000

CLI flags

FlagDefaultDescription
--server, -sDirectory to serve
--files, -fGlob patterns to watch (repeatable)
--watch, -wWatch server roots in addition to --files
--ignoreIgnore patterns for file watchers (repeatable)
--port3000Port to listen on
--no-uiDisable the UI panel
--no-notifyDisable the notification overlay
--no-ghost-modeDisable scroll/click/location/form sync
--corsEnable CORS headers
--log-levelinfoPino log level, for example silent, trace, debug, info, warn, error, or fatal
--log-connectionsLog browser connection events at info level
--help, -hShow help text
--version, -vShow version

domstack-sync init writes domstack-sync.config.mjs using export default. On startup, the CLI loads the first config file it finds in this order: domstack-sync.config.mjs, .mts, .js, then .ts. TypeScript config files rely on Node's built-in type stripping.

API

import { createServer, parseOptions } from '@domstack/sync'

const sync = await createServer({
  server: './public',
  files: ['public/**/*.css', 'public/**/*.html'],
  port: 3000,
})

console.log(sync.url)    // http://localhost:3000
console.log(sync.uiUrl)  // http://localhost:3001

// Trigger a full reload
sync.reload()

// CSS-inject a specific file (falls back to full reload if not matched)
sync.reload(['styles/main.css'])

// Show a notification overlay in connected browsers
sync.notify('Build complete')

// Stream integration — pipe any { path } objects through to trigger reloads
someReadableStream.pipe(sync.stream())

// Listen for server-side events
sync.events.on('client:connect', (info) => console.log('connected', info.ua))
sync.events.on('client:disconnect', (id) => console.log('disconnected', id))
sync.events.on('file:change', (evt) => console.log('changed', evt.path))

// Pause / resume watcher-triggered reloads (e.g. during a build)
sync.pause()
sync.resume()

// Graceful shutdown
await sync.exit()

Logging

Standalone usage creates a pretty Pino logger automatically. When embedding @domstack/sync in another tool, pass a raw Pino logger and keep formatting ownership in the parent process:

import pino from 'pino'
import { createLogger, createServer, logAccessUrls } from '@domstack/sync'

// Standalone helper: returns a regular pino.Logger with domstack-sync's pretty formatter.
const standaloneLogger = createLogger('info')

// Embedded/library usage: pass your own raw pino.Logger.
const ownerLogger = pino({ level: 'info' })
const sync = await createServer({
  server: './public',
  files: ['public/**/*.css', 'public/**/*.html'],
  logger: ownerLogger.child({ component: 'sync', logPrefix: '[domstack-sync]' }),
})

logAccessUrls(standaloneLogger, {
  local: sync.url,
  ui: sync.uiUrl,
})

logAccessUrls(logger, urls) is exported for callers that want the same access-URL table with their own Pino logger.

Options

OptionTypeDefaultDescription
portnumber3000Port to listen on (falls back to OS-assigned if taken)
serverstring | boolean | string[] | objectfalseDirectory or directories to serve statically
filesstring | string[] | object[][]Glob patterns or chokidar watch objects to watch for changes
ghostModeboolean | { scroll, clicks, location, forms }all trueSync interactions across connected browsers
loggerpino.LoggerRaw Pino logger supplied by an embedding owner; when omitted, sync creates its own standalone pretty logger
logLevelPino log level string'info'Log verbosity used by the standalone logger when logger is omitted
logConnectionsbooleanfalseLog browser connection events at info level
uiboolean | { port: number }trueUI panel — false disables, { port } pins the port
notifybooleantrueShow notification overlay in connected browsers
corsbooleanfalseAdd CORS headers to all responses
injectChangesbooleantrueInject matching file changes instead of full reload
injectFileTypesstring[]['css', 'png', 'jpg', 'jpeg', 'svg', 'gif', 'webp', 'map']Extensions eligible for file injection
tagNamesRecord<string, string>built-in asset tag mapElement tag names used for non-CSS file injection
codeSyncbooleantrueBroadcast reload and file-injection messages
reloadDebouncenumber500Milliseconds to debounce file-change reloads
reloadDelaynumber0Milliseconds to delay reload after a change
reloadThrottlenumber0Minimum milliseconds between reload broadcasts
scrollThrottlenumber0Minimum milliseconds between scroll sync messages
scrollElementsstring[][]CSS selectors eligible for element scroll sync
scrollElementMappingstring[][]Selector mapping for scroll sync between different layouts
scrollProportionallybooleantrueSync scroll position proportionally instead of raw pixels
watchbooleanfalseAdd server roots and routes to watched files
ignorestring | string[]Ignore patterns merged into watcher options
watchOptionsobject{}Options passed through to chokidar
watchEventsstring[]['change']Chokidar event names that trigger reloads
snippetbooleantrueInject the browser client snippet into HTML responses
snippetOptionsobject{}Whitelist, blacklist, ignore paths, or custom injection rule
rewriteRulesobject[][]HTML rewrite rules applied before snippet injection
pluginsarray[]BrowserSync-compatible plugin entries
cwdstringprocess.cwd()Working directory for resolving server and files

TypeScript

All types are exported:

import type { AccessUrls, BsInstance, BsOptions, BsOptionsInput, LoggerOptions, LoggerStreams } from '@domstack/sync'
import type { ServerToClientMessage, ClientToServerMessage } from '@domstack/sync'

How it works

  • Script injection — an IIFE <script> tag is injected immediately after the opening <body> tag (or appended if there is no <body>) in every HTML response. The injected script connects to the WebSocket server.
  • File injection — when a watched injectable file changes and injectChanges: true, matching DOM assets are cache-busted in place without a full page reload. CSS stylesheets, imported stylesheets, images, inline image URLs, and configured asset tags are supported. Falls back to a full reload if no matching asset is found.
  • Ghost mode — scroll position, clicks, location changes, and form input changes in one browser are relayed to all other connected browsers via the WebSocket server. Disable with ghostMode: false or --no-ghost-mode.
  • UI panel — a separate Fastify server on an auto-detected port shows connected browsers, file-change history, and server URLs. Disable with ui: false or --no-ui.
  • Port selection — the requested port is tried first. If it is already in use, the OS assigns a free ephemeral port automatically.

License

MIT

Keywords

live-reload

FAQs

Package last updated on 28 Jun 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts