Packaging
Building distributable releases of Sigilweaver.
Overview
Sigilweaver is distributed as a standalone desktop application. The build process:
- Backend: PyInstaller bundles Python code + interpreter into a single executable
- Frontend: Vite builds the React app, Electron packages everything
The result is a single application with zero external dependencies. Users don't need Python or Node.js installed.
Quick Build
# From repo root
./scripts/build.sh
This builds for your current platform. Output goes to frontend/dist/.
Platform-Specific
# Linux
cd frontend && npm run build:linux
# Windows
cd frontend && npm run build:win
# macOS
cd frontend && npm run build:mac
Note: You can only build for your current platform. Cross-compilation is limited.
Build Process Details
Step 1: Backend Executable
cd backend
source .venv/bin/activate
pip install -e ".[build]" # Includes PyInstaller
../scripts/build_backend.sh
PyInstaller analyzes app/main.py and bundles:
- All Python code in
app/ - Python interpreter
- All dependencies (FastAPI, Uvicorn, Polars)
- Native libraries
Result: backend/dist/backend (~50-100MB)
Step 2: Frontend + Electron
cd frontend
npm run build
npm run dist:linux # or dist:win, dist:mac
This:
- Vite builds the React app to
frontend/dist/ - electron-builder packages everything
- Includes the backend executable from
backend/dist/
Output Artifacts
Linux
| File | Description |
|---|---|
Sigilweaver-<version>.AppImage | Single-file, runs anywhere |
sigilweaver_<version>_amd64.snap | Snap package |
Windows
| File | Description |
|---|---|
Sigilweaver Setup <version>.exe | NSIS installer |
Sigilweaver <version>.exe | Portable (no install) |
macOS
| File | Description |
|---|---|
Sigilweaver-<version>.dmg | Standard Mac installer |
Sigilweaver-<version>-mac.zip | Zipped app bundle |
Build Configurations
Full vs Client
Two build variants exist:
- Full: Includes embedded backend (standalone)
- Client: Frontend only (requires external backend)
# Full version (default)
npm run build:linux
# Client version
npm run build:linux:client
Client builds are smaller (~100MB vs ~200MB) but require a separate backend installation.
electron-builder Config
Configuration lives in package.json and electron-builder*.json:
{
"build": {
"appId": "app.sigilweaver",
"productName": "Sigilweaver",
"directories": {
"output": "dist"
},
"extraResources": [
{
"from": "../backend/dist",
"to": "backend"
}
],
"linux": {
"target": ["AppImage", "snap"],
"category": "Development"
},
"win": {
"target": ["nsis", "portable"]
},
"mac": {
"target": ["dmg", "zip"],
"category": "public.app-category.developer-tools"
}
}
}
PyInstaller Spec
Backend bundling is configured in backend/sigilweaver.spec:
a = Analysis(
['app/main.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=['uvicorn.logging', 'uvicorn.loops', ...],
hookspath=[],
...
)
Hidden imports are manually specified because PyInstaller can't detect dynamic imports.
How It Works at Runtime
Production Mode
- User launches Sigilweaver
- Electron main process starts
- Spawns backend executable from
resources/backend/ - Waits for backend health check (
/api/health/) - Opens main window pointing to bundled frontend
- On quit, terminates backend process
Development Mode
- Developer runs
./scripts/dev.sh - Backend runs from Python source with hot reload
- Frontend runs from Vite dev server with hot reload
- Electron (optional) connects to dev server
The app detects development mode and adjusts behavior automatically.
File Size
Typical sizes:
| Component | Size |
|---|---|
| Backend executable | 50-100 MB |
| Frontend bundle | 5-10 MB |
| Electron runtime | 80-100 MB |
| Total (full) | ~200 MB |
| Total (client) | ~100 MB |
The backend is large because it includes the entire Python runtime and Polars (which is written in Rust and fairly hefty).
Testing Builds
After building, test on a clean system:
# Linux
./frontend/dist/Sigilweaver-*.AppImage
# Or unpack and run
./frontend/dist/linux-unpacked/sigilweaver
Verify:
- App launches without errors
- Backend starts (check Developer Tools console)
- Can load a CSV file
- Can execute a workflow
- Output files are written correctly
Troubleshooting
Backend not found
The backend executable must exist at build time:
# Build backend first
cd backend && ./build_executable.sh
# Then build frontend
cd frontend && npm run build:linux
Large build size
Normal. PyInstaller bundles the entire Python runtime. UPX compression is enabled by default.
Missing Python modules
Add to hiddenimports in sigilweaver.spec:
hiddenimports=[
'uvicorn.logging',
'your.missing.module',
]
Platform-specific issues
- Linux: Builds AppImage and Snap on any Linux distro
- Windows: NSIS installer only builds on Windows (or with Wine)
- macOS: Must build on macOS; code signing requires Developer ID
Code Signing
For production releases:
Windows
Authenticode signing reduces SmartScreen warnings:
# In electron-builder config
"win": {
"sign": "./sign.js",
"certificateFile": "./cert.pfx",
"certificatePassword": "${env.CERT_PASSWORD}"
}
macOS
Apple notarization is required for Gatekeeper:
# In electron-builder config
"mac": {
"hardenedRuntime": true,
"entitlements": "./entitlements.plist",
"notarize": {
"teamId": "${env.APPLE_TEAM_ID}"
}
}
Next: Releasing for CI/CD and distribution.