
Working as the captain of University of Tehran Nacional Formula Student team our mechanical engineers used to sort and manage their parts manually using FOLDERS and directories like "/GearboxV2-21AUG" and there was no shared space or over the network solution, everything was being done like the stone age using USB's sometimes, and my first thought was there has got to be a selfhost offline FOSS solution for mechanical engineering projects like we have git for software, and they said no, and shit they were right.
SolidSync is two pieces: one server on your shop network (it holds the org and the files), and the desktop client your teammates install to use it. No source code, no git, no account, no cloud.
One machine on your network runs the server. That machine needs Node.js 20+ and git installed; nothing else.
npm install -g solidsync
solidsync-server serve
That's it — the server prints the address your team should point at (e.g.
http://192.168.1.50:3020) and stays running until you press Ctrl+C. Hand that
address out to your team.
Everyone else just downloads the client for their machine from the releases page — no install wizard, no account, no dependencies:
SolidSync-<version>-x64.exe and double-click to
install, or grab the -x64-portable.zip and run it without installing.SolidSync-<version>-amd64.deb and run
sudo apt install ./SolidSync-<version>-amd64.deb.On first launch the client asks for your name and the server address from
Part 1 (http://<LAN-IP>:3020), then you're in.
SolidSync is a Local Shop-floor part sync tool that just works. you run it on a potato server you have lying around and it becomes a server, people on your team install the Client and. An advanced file explorer for mechanical engineers that replaces manually-dated shared folders with version history, a single source of truth for "which file is current," and basic collaboration signals.
No git required to use it. No login. No PDM seat.
ORG → PROJECTS → SECTIONS → PARTS
Versioning, not a VCS. Parts stay linear — there is no merge UI or engine, no part-level branching, and no assembly-reference resolution. Two people can still submit divergent versions of the same part; that's a coordination gap, not a technical conflict. The work status (red/yellow) is the social prevention; the sync status makes a stale local copy obvious before someone saves blind.
Vocabulary. The UI deliberately avoids VCS jargon — no commit/push/pull/ merge/clone/checkout. The product says throw in, save a version, set as head, sync, out of sync / current.
The client is a plain desktop app — no login, no account, no install fluff. It runs on any PC on the shop floor and needs nothing but itself.
Windows — the build produces an NSIS installer and a portable .exe
(npm run build:win → dist/SolidSync-<version>-x64.exe). Drop the installer
on a shared drive or your release page; teammates double-click and it's done.
The portable .exe doesn't even need installing.
Linux — npm run build:linux produces a .deb
(dist/SolidSync-<version>-amd64.deb), installable with sudo apt install ./SolidSync-0.2.0-amd64.deb.
Other platforms / building it yourself — clone the repo and build:
npm install
npm run build # compile main / preload / renderer
npm run build:win # Windows installer + portable (run on a Windows box)
npm run build:linux # Linux .deb
App icon. Drop your icon.png (at least 512×512, transparent background) at
packages/client/build/icon.png. It's used for the packaged app icon, the
installer, the .desktop entry, and the in-app window icon. The repo ships a
placeholder — overwrite it before shipping.
On first run, enter your name and type the address your admin printed when
they started the server (http://<LAN-IP>:3020).
One machine on the shop network runs the headless server — the org lives there, clients just point at it. Needs Node.js 20+ and git (the version-storage engine) on that machine.
npm install -g solidsync
solidsync-server serve
That's it. It binds 0.0.0.0:3020 by default, prints the URL to hand out
(http://<LAN-IP>:3020), and stays in the foreground until Ctrl+C.
Run it in the background with --daemon — the server detaches, logs to
<dir>/server.log by default, and the command prints the pid + URL, then exits:
solidsync-server serve --daemon --name "Fab Shop"
# SolidSync server running in the background
# pid : 1234
# log : ~/.solidsync/server.log
# tell everyone: http://192.168.1.50:3020
# stop it : solidsync-server stop (or kill 1234)
Stop or restart it by name — no need to remember the pid:
solidsync-server stop # graceful stop (SIGTERM, waits up to 15s)
solidsync-server restart # stop, then start again with the same options
restart replays the launch record the daemon wrote at startup, so it comes
back with the same port, name, and TLS settings even after a reboot. Set
--log PATH for a different log location, --pidfile PATH to move the pid
file.
Everything is optional; defaults work for most shops:
| Option | Env var | Default | Meaning |
|---|---|---|---|
--dir PATH | SOLIDSYNC_DIR | ~/.solidsync | where org data lives |
--port N | SOLIDSYNC_PORT | 3020 | HTTP port |
--host IP | SOLIDSYNC_HOST | 0.0.0.0 | bind address |
--name NAME | SOLIDSYNC_NAME | Shop | org name shown in the UI |
--daemon | SOLIDSYNC_DAEMON | off | run serve in the background |
--log PATH | SOLIDSYNC_LOG | <dir>/server.log | log file for --daemon |
--pidfile PATH | SOLIDSYNC_PIDFILE | <dir>/server.pid | pid file for --daemon (read by stop/restart) |
solidsync-server serve --port 3020 --name "Fab Shop"
--tls to also serve HTTPS on --tls-port (default 3443).
First run generates a throwaway CA + cert under <dir>/tls/ and prints the CA
fingerprint; clients verify against it on first connect. See the TLS section
below.solidsync-server backup snapshots the whole org into one
archive, or just copy the --dir folder.Everything the GUI can do over HTTP, the CLI can do from a terminal — run against a running server unless noted.
solidsync-server serve # run the server in the foreground
solidsync-server serve --daemon # run it in the background (logs to <dir>/server.log)
solidsync-server stop # stop the background server
solidsync-server restart # stop, then start again with the same options
solidsync-server init # create/repair the org data folder
solidsync-server health # is the server up? prints JSON
solidsync-server list # print the whole org tree
solidsync-server list --json # raw org snapshot, machine-readable
solidsync-server import step.step # throw a file in (first project/section)
solidsync-server import step.step --project "Gearbox V2" --section Drivetrain
solidsync-server status 482913 # show a part's state (prefix ok)
solidsync-server status 482913 --set red # stamp work status: red|yellow|green
solidsync-server branch "Gearbox V2" "Gearbox V2 Copy" # admin-only project copy
solidsync-server archive "Gearbox V2" # move out of the active list
solidsync-server unarchive "Gearbox V2" # bring it back
solidsync-server backup # snapshot whole org to tar.gz
solidsync-server backup /srv/solidsync-backups/org-$(date +%F).tar.gz
solidsync-server version # print the server version
Point any command at a remote server with --url http://<LAN-IP>:3020 (and
--ca PATH for HTTPS). The full reference lives in
packages/server/README.md; solidsync-server --help prints the usage inline.
First run shows a one-time setup: enter your name and point at the shop server (IP and port). No account, no password. The client never hosts the org — it is a mirror of whatever the server has (structure synced automatically, version files pulled on demand). Every server you connect to is remembered for one-click switching in the top bar.
Requires:
npm install # if the Electron binary wasn't downloaded, run:
node node_modules/electron/install.js
| Command | Purpose |
|---|---|
npm run dev | Run in development (hot reload) |
npm run build | Compile main / preload / renderer |
npm start | Preview a production build |
npm test | Run the vitest suite |
npm run typecheck | TypeScript checks (node + web) |
npm run build:win | Build Windows installer (NSIS + portable) |
npm run pack:win | Build an unpacked Windows folder |
npm run build:linux | Build a Linux .deb |
Default port is 3020. Server binds 0.0.0.0 so teammates can reach it over
the LAN; the top bar shows the reachable address.
Public CAs won't issue certificates for LAN IPs, so SolidSync does its own TOFU (trust on first use):
--tls to also serve HTTPS on --tls-port (default
3443, or $SOLIDSYNC_TLS_PORT). On first run it generates a throwaway CA
<org-dir>/tls/ and prints the CA fingerprint.
Plain HTTP stays on the original port, so old clients keep working during a
rollout.server-ca.pem) and every later session verifies against
it. "Forget server identity" in Server settings clears it (e.g. after a
server reinstall).--url https://host:port --ca PATH (or
set $SOLIDSYNC_CA) so health / list / import trust the server.The client stores only what it needs to talk to and mirror the server. The org itself lives on the server machine.
Client machine — user-data folder (e.g. %APPDATA%/SolidSync on Windows):
├── config.json # this machine's setup (name, active server, saved servers)
├── server-ca.pem # pinned server CA (HTTPS trust)
└── mirror/<projectId>/ # local mirror of the server's projects, one git repo each
Server machine — SOLIDSYNC_DIR (default ~/.solidsync):
├── solidsync.db # metadata: projects, sections, parts, versions, statuses
├── tls/ # generated CA + server cert (when serving with --tls)
├── server.pid # pid of the background server (when running with --daemon)
├── server.launch.json # launch record used by `restart`
└── repos/<projectId>/ # one git repo per project holding the file bytes
sql.js) on the server — trivially backed
up by copying it; the org is the whole server data folder.isomorphic-git) of the org
structure only — the sync layer fetches projects/sections/parts/versions
and prunes anything that vanished from the server, so browsing stays current
and deleted content disappears from the GUI on the next sync. Version files
are pulled on demand via Download (progress + cancel) and tracked per version,
so you only download what you actually open. Anything already on the drive
opens and browses offline.┌────────────────────────────────────────────────────────────┐
│ Electron app (GUI is display + requests only) │
│ ┌──────────────┐ IPC ┌───────────────────────────┐ │
│ │ Renderer │ ─────────► │ Main │ │
│ │ (React) │ │ ├─ SyncService (client) │ │
│ └──────────────┘ │ │ polls /health, │ │
│ │ │ reconciles mirror │ │
│ │ └───┬────────────────────┘ │
└──────────────────────────────┼──────┼─────────────────────┘
▼ (http/https)
┌──────────────────────────┐
│ Express REST server │
│ ├─ sql.js (SQLite) │
│ └─ git binary (repos) │
└──────────────────────────┘
--tls); no websockets. Clients poll
/api/health every few seconds and refetch the org snapshot when the
revision number moves.child_process — reliable on the host, no CLI output to parse.isomorphic-git, so no external
git install is needed on shop PCs.Electron · React 19 · TypeScript · Vite (electron-vite) · Tailwind CSS ·
Express 5 · sql.js (SQLite) · isomorphic-git · Vitest
29 commits
TypeScript
94.0%
JavaScript
5.7%

Working as the captain of University of Tehran Nacional Formula Student team our mechanical engineers used to sort and manage their parts manually using FOLDERS and directories like "/GearboxV2-21AUG" and there was no shared space or over the network solution, everything was being done like the stone age using USB's sometimes, and my first thought was there has got to be a selfhost offline FOSS solution for mechanical engineering projects like we have git for software, and they said no, and shit they were right.
SolidSync is two pieces: one server on your shop network (it holds the org and the files), and the desktop client your teammates install to use it. No source code, no git, no account, no cloud.
One machine on your network runs the server. That machine needs Node.js 20+ and git installed; nothing else.
npm install -g solidsync
solidsync-server serve
That's it — the server prints the address your team should point at (e.g.
http://192.168.1.50:3020) and stays running until you press Ctrl+C. Hand that
address out to your team.
Everyone else just downloads the client for their machine from the releases page — no install wizard, no account, no dependencies:
SolidSync-<version>-x64.exe and double-click to
install, or grab the -x64-portable.zip and run it without installing.SolidSync-<version>-amd64.deb and run
sudo apt install ./SolidSync-<version>-amd64.deb.On first launch the client asks for your name and the server address from
Part 1 (http://<LAN-IP>:3020), then you're in.
SolidSync is a Local Shop-floor part sync tool that just works. you run it on a potato server you have lying around and it becomes a server, people on your team install the Client and. An advanced file explorer for mechanical engineers that replaces manually-dated shared folders with version history, a single source of truth for "which file is current," and basic collaboration signals.
No git required to use it. No login. No PDM seat.
ORG → PROJECTS → SECTIONS → PARTS
Versioning, not a VCS. Parts stay linear — there is no merge UI or engine, no part-level branching, and no assembly-reference resolution. Two people can still submit divergent versions of the same part; that's a coordination gap, not a technical conflict. The work status (red/yellow) is the social prevention; the sync status makes a stale local copy obvious before someone saves blind.
Vocabulary. The UI deliberately avoids VCS jargon — no commit/push/pull/ merge/clone/checkout. The product says throw in, save a version, set as head, sync, out of sync / current.
The client is a plain desktop app — no login, no account, no install fluff. It runs on any PC on the shop floor and needs nothing but itself.
Windows — the build produces an NSIS installer and a portable .exe
(npm run build:win → dist/SolidSync-<version>-x64.exe). Drop the installer
on a shared drive or your release page; teammates double-click and it's done.
The portable .exe doesn't even need installing.
Linux — npm run build:linux produces a .deb
(dist/SolidSync-<version>-amd64.deb), installable with sudo apt install ./SolidSync-0.2.0-amd64.deb.
Other platforms / building it yourself — clone the repo and build:
npm install
npm run build # compile main / preload / renderer
npm run build:win # Windows installer + portable (run on a Windows box)
npm run build:linux # Linux .deb
App icon. Drop your icon.png (at least 512×512, transparent background) at
packages/client/build/icon.png. It's used for the packaged app icon, the
installer, the .desktop entry, and the in-app window icon. The repo ships a
placeholder — overwrite it before shipping.
On first run, enter your name and type the address your admin printed when
they started the server (http://<LAN-IP>:3020).
One machine on the shop network runs the headless server — the org lives there, clients just point at it. Needs Node.js 20+ and git (the version-storage engine) on that machine.
npm install -g solidsync
solidsync-server serve
That's it. It binds 0.0.0.0:3020 by default, prints the URL to hand out
(http://<LAN-IP>:3020), and stays in the foreground until Ctrl+C.
Run it in the background with --daemon — the server detaches, logs to
<dir>/server.log by default, and the command prints the pid + URL, then exits:
solidsync-server serve --daemon --name "Fab Shop"
# SolidSync server running in the background
# pid : 1234
# log : ~/.solidsync/server.log
# tell everyone: http://192.168.1.50:3020
# stop it : solidsync-server stop (or kill 1234)
Stop or restart it by name — no need to remember the pid:
solidsync-server stop # graceful stop (SIGTERM, waits up to 15s)
solidsync-server restart # stop, then start again with the same options
restart replays the launch record the daemon wrote at startup, so it comes
back with the same port, name, and TLS settings even after a reboot. Set
--log PATH for a different log location, --pidfile PATH to move the pid
file.
Everything is optional; defaults work for most shops:
| Option | Env var | Default | Meaning |
|---|---|---|---|
--dir PATH | SOLIDSYNC_DIR | ~/.solidsync | where org data lives |
--port N | SOLIDSYNC_PORT | 3020 | HTTP port |
--host IP | SOLIDSYNC_HOST | 0.0.0.0 | bind address |
--name NAME | SOLIDSYNC_NAME | Shop | org name shown in the UI |
--daemon | SOLIDSYNC_DAEMON | off | run serve in the background |
--log PATH | SOLIDSYNC_LOG | <dir>/server.log | log file for --daemon |
--pidfile PATH | SOLIDSYNC_PIDFILE | <dir>/server.pid | pid file for --daemon (read by stop/restart) |
solidsync-server serve --port 3020 --name "Fab Shop"
--tls to also serve HTTPS on --tls-port (default 3443).
First run generates a throwaway CA + cert under <dir>/tls/ and prints the CA
fingerprint; clients verify against it on first connect. See the TLS section
below.solidsync-server backup snapshots the whole org into one
archive, or just copy the --dir folder.Everything the GUI can do over HTTP, the CLI can do from a terminal — run against a running server unless noted.
solidsync-server serve # run the server in the foreground
solidsync-server serve --daemon # run it in the background (logs to <dir>/server.log)
solidsync-server stop # stop the background server
solidsync-server restart # stop, then start again with the same options
solidsync-server init # create/repair the org data folder
solidsync-server health # is the server up? prints JSON
solidsync-server list # print the whole org tree
solidsync-server list --json # raw org snapshot, machine-readable
solidsync-server import step.step # throw a file in (first project/section)
solidsync-server import step.step --project "Gearbox V2" --section Drivetrain
solidsync-server status 482913 # show a part's state (prefix ok)
solidsync-server status 482913 --set red # stamp work status: red|yellow|green
solidsync-server branch "Gearbox V2" "Gearbox V2 Copy" # admin-only project copy
solidsync-server archive "Gearbox V2" # move out of the active list
solidsync-server unarchive "Gearbox V2" # bring it back
solidsync-server backup # snapshot whole org to tar.gz
solidsync-server backup /srv/solidsync-backups/org-$(date +%F).tar.gz
solidsync-server version # print the server version
Point any command at a remote server with --url http://<LAN-IP>:3020 (and
--ca PATH for HTTPS). The full reference lives in
packages/server/README.md; solidsync-server --help prints the usage inline.
First run shows a one-time setup: enter your name and point at the shop server (IP and port). No account, no password. The client never hosts the org — it is a mirror of whatever the server has (structure synced automatically, version files pulled on demand). Every server you connect to is remembered for one-click switching in the top bar.
Requires:
npm install # if the Electron binary wasn't downloaded, run:
node node_modules/electron/install.js
| Command | Purpose |
|---|---|
npm run dev | Run in development (hot reload) |
npm run build | Compile main / preload / renderer |
npm start | Preview a production build |
npm test | Run the vitest suite |
npm run typecheck | TypeScript checks (node + web) |
npm run build:win | Build Windows installer (NSIS + portable) |
npm run pack:win | Build an unpacked Windows folder |
npm run build:linux | Build a Linux .deb |
Default port is 3020. Server binds 0.0.0.0 so teammates can reach it over
the LAN; the top bar shows the reachable address.
Public CAs won't issue certificates for LAN IPs, so SolidSync does its own TOFU (trust on first use):
--tls to also serve HTTPS on --tls-port (default
3443, or $SOLIDSYNC_TLS_PORT). On first run it generates a throwaway CA
<org-dir>/tls/ and prints the CA fingerprint.
Plain HTTP stays on the original port, so old clients keep working during a
rollout.server-ca.pem) and every later session verifies against
it. "Forget server identity" in Server settings clears it (e.g. after a
server reinstall).--url https://host:port --ca PATH (or
set $SOLIDSYNC_CA) so health / list / import trust the server.The client stores only what it needs to talk to and mirror the server. The org itself lives on the server machine.
Client machine — user-data folder (e.g. %APPDATA%/SolidSync on Windows):
├── config.json # this machine's setup (name, active server, saved servers)
├── server-ca.pem # pinned server CA (HTTPS trust)
└── mirror/<projectId>/ # local mirror of the server's projects, one git repo each
Server machine — SOLIDSYNC_DIR (default ~/.solidsync):
├── solidsync.db # metadata: projects, sections, parts, versions, statuses
├── tls/ # generated CA + server cert (when serving with --tls)
├── server.pid # pid of the background server (when running with --daemon)
├── server.launch.json # launch record used by `restart`
└── repos/<projectId>/ # one git repo per project holding the file bytes
sql.js) on the server — trivially backed
up by copying it; the org is the whole server data folder.isomorphic-git) of the org
structure only — the sync layer fetches projects/sections/parts/versions
and prunes anything that vanished from the server, so browsing stays current
and deleted content disappears from the GUI on the next sync. Version files
are pulled on demand via Download (progress + cancel) and tracked per version,
so you only download what you actually open. Anything already on the drive
opens and browses offline.┌────────────────────────────────────────────────────────────┐
│ Electron app (GUI is display + requests only) │
│ ┌──────────────┐ IPC ┌───────────────────────────┐ │
│ │ Renderer │ ─────────► │ Main │ │
│ │ (React) │ │ ├─ SyncService (client) │ │
│ └──────────────┘ │ │ polls /health, │ │
│ │ │ reconciles mirror │ │
│ │ └───┬────────────────────┘ │
└──────────────────────────────┼──────┼─────────────────────┘
▼ (http/https)
┌──────────────────────────┐
│ Express REST server │
│ ├─ sql.js (SQLite) │
│ └─ git binary (repos) │
└──────────────────────────┘
--tls); no websockets. Clients poll
/api/health every few seconds and refetch the org snapshot when the
revision number moves.child_process — reliable on the host, no CLI output to parse.isomorphic-git, so no external
git install is needed on shop PCs.Electron · React 19 · TypeScript · Vite (electron-vite) · Tailwind CSS ·
Express 5 · sql.js (SQLite) · isomorphic-git · Vitest
29 commits
TypeScript
94.0%
JavaScript
5.7%