Captures two install upgrades in dependency order so a future session can pick them up without re-thinking: Tier 1 — scripts/setup.sh: one-liner installer for terminal-comfortable designers. Auto-generates JWT_SECRET, prompts for admin email/password, brings up docker compose, opens the browser. Floor: Docker Desktop must be installed (script exits with a friendly install link if not). Tier 2 — native installer: .dmg / .exe with no Docker, no terminal. Replaces MinIO with a local-filesystem storage adapter, bundles the Node backend + frontend dist into a single binary via pkg, wraps in a Tauri tray app. Designer double-clicks, gets a menu-bar icon, clicks "Open RefBoard." Both unchecked in README roadmap and detailed in docs/install-roadmap.md with file layout, estimated effort, and open questions.
7.8 KiB
Install Roadmap — Making RefBoard Designer-Friendly
Goal: a designer with zero terminal experience should be able to install and run RefBoard on their own laptop. Today's docker compose up story is fine for technical users; not for designers. This document captures the two upgrade tiers we've planned, in dependency order, so any future contributor (including future-me) can pick up cleanly.
Tier 1 — setup.sh (one-click for terminal-comfortable users)
Audience: designers who can copy-paste a single line into Terminal, but won't manage a docker-compose stack.
Floor: Docker Desktop must be installed. The script detects this and fails with a friendly install link rather than a stack trace.
Behaviour
- Detect OS (
uname) → macOS / Linux. (Windows handled by siblingsetup.ps1.) - Check
docker infois reachable. If not:- macOS: print Docker Desktop download URL (
https://www.docker.com/products/docker-desktop/), exit cleanly. - Linux: print apt/dnf install commands, exit cleanly.
- macOS: print Docker Desktop download URL (
- If
.envdoesn't exist:- Copy
.env.example → .env. - Replace
JWT_SECRET=...with a freshly-generated secret (openssl rand -base64 64). - Prompt for admin email and password (with sensible defaults like
admin@local/ a generated 16-char password printed at the end). - Set
SEED_ADMIN_EMAIL/SEED_ADMIN_PASSWORDso first boot creates the admin.
- Copy
- Run
docker compose up -d --build. - Wait until
curl http://localhost:8000/healthreturns 200 (poll, max 60s). - Print:
- The URL (
http://localhost:8000) - Admin email + password (especially if generated)
- Reminder to back up
./.docker-data/
- The URL (
- Open the URL in the default browser (
openon macOS,xdg-openon Linux).
File location
scripts/setup.sh — executable. README's quick-start gets a one-liner ahead of the manual docker compose up:
curl -fsSL https://raw.githubusercontent.com/metalfinger/refboard/main/scripts/setup.sh | bash
Estimated effort
~1 hour. Mostly bash plumbing — the underlying stack already works.
Windows variant
scripts/setup.ps1 mirrors the same logic for PowerShell. Roughly same effort.
Tier 2 — Native installer (.dmg / .exe) with zero dependencies
Audience: designers who only know how to double-click an installer. The actual mass market.
Floor: none — no Docker, no Node, no Terminal. Just download, double-click.
Architecture
┌─────────────────────────────────────┐
│ RefBoard.app (Tauri/Electron shell)│
│ ┌──────────────────────────────┐ │
│ │ Bundled Node binary │ │ ← pkg or nexe
│ │ + frontend dist │ │
│ │ + better-sqlite3 │ │
│ │ + sharp (prebuilt for arch) │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ ~/Library/ │ │ ← local FS
│ │ RefBoard/ │ │ storage adapter
│ │ refboard.db │ │ replaces MinIO
│ │ media/... │ │
│ └─────────────────┘ │
└─────────────────────────────────────┘
Pieces to build (in order)
-
Local-filesystem storage adapter (~150 lines). New file
backend/storage-fs.jsexposing the same interface asbackend/minio.js:putBuffer(name, buf, mime)→ write to${DATA_DIR}/media/${name}getObject(name),getPartialObject(name, start, len)→ fs.createReadStream with byte rangeremoveObject(name),removeObjects(names)listObjectsV2(prefix)→ glob/fs.readdirbucketExists,makeBucket→ no-op (justmkdir -p)
Pick the active backend at boot via env var
STORAGE_BACKEND=minio|fs. Defaultminiofor Docker users; native installer setsfs. -
ffmpeg + poppler bundling. Both are required for video posters and PDF rendering. Two options:
- Bundle prebuilt binaries inside the app package (handle license attribution; both are GPL/LGPL — review before shipping).
- Detect at runtime and degrade gracefully (already done for poppler; extend to ffmpeg). Designers who skip these still get image uploads.
-
Single binary via
pkg. Bundle Node + backend + frontend dist:pnpm dlx pkg backend/server.js \ --targets node20-macos-arm64,node20-macos-x64,node20-win-x64 \ --assets "frontend/dist/**/*" \ --output dist/refboardbetter-sqlite3andsharpship native bindings; verify they survivepkg's fs-snapshot. If not, switch to@yao-pkg/pkg(maintained fork) ornexe. -
Tauri or Electron wrapper. Recommend Tauri (smaller, native shell, Rust):
- Spawns the bundled binary on app launch with
STORAGE_BACKEND=fs,DATA_DIR=$APPSUPPORT/RefBoard. - Picks an available high port (default 8000, falls back if taken).
- Menu-bar / system-tray icon with: "Open RefBoard" (opens
http://localhost:<port>in the user's default browser), "Show Data Folder" (Finder reveal), "Quit." - On first launch, creates the data folder and seeds the admin from a generated password shown in a one-time onboarding window.
- Spawns the bundled binary on app launch with
-
Code signing + notarization.
- macOS: Apple Developer ID ($99/yr),
codesign+xcrun notarytool. Without notarization, Gatekeeper blocks the .dmg. Mandatory. - Windows: SignTool with an EV cert. SmartScreen warning otherwise. Optional but worth it.
- macOS: Apple Developer ID ($99/yr),
-
Auto-update. Tauri's updater plugin or Electron's
autoUpdater, pointed at GitHub Releases. Not required for v1. -
Distribution. GitHub Releases as the source of truth. README links to the latest
.dmgand.exeand includes a checksum.
Estimated effort
- Storage adapter: 2 hours
- Binary bundling: 4 hours (mostly pkg/sharp friction)
- Tauri shell: 4 hours
- Code signing setup: 2 hours
- Total: ~1 day for a working build, ~2 days with code signing + first auto-update wired
Open questions to decide before starting
- Multi-user on a native install — is that a thing we want? A designer running it locally is mostly solo. But what about "I want my designer friend on the LAN to join my board"? The native build can still expose port 8000 on the host's IP — just need a "Share with LAN" toggle in the tray menu. Worth scoping.
- ffmpeg / poppler licensing. Both are GPL/LGPL with shipping requirements. Review before bundling. May be cleaner to download them on first launch with the user's consent rather than ship in the app bundle.
- Storage swap or bridge? If
STORAGE_BACKEND=fsand someone later wants to migrate tominio, do we offer annpm run migrate-storagehelper? Probably yes.
Tier 3 — Hosted SaaS (parked)
refboard.app style: I host it, designers sign up by email, instant access. Easiest possible UX, but it changes the project from "MIT, self-hosted" to "freemium SaaS." Costs and scope balloon (Stripe billing, multi-tenant DB partitioning, hostname routing, abuse handling). Parked unless there's clear demand after Tier 2 ships.
Pickup checklist for the next session
- Decide which tier to start. Recommend Tier 1 first (1 hour, low risk, immediately ships value).
- For Tier 1: Just write
scripts/setup.sh, smoke-test on a clean Mac, link from README. - For Tier 2: Start with the storage adapter (fully testable in isolation by setting
STORAGE_BACKEND=fswith the existing Docker stack). Once that ships, the bundling work is mechanical.