v13.0.0 - Electron React App
A major release. The IPC layer is rebuilt on electron-conveyor, and main is now a minimal starting shell with the interactive playground moved to the demo branch.
Type-safe IPC - Electron Conveyor
- Define once, typed everywhere. Write a feature in the main process and the renderer gets a fully typed client for free. No channel strings, no client to write, no types to keep in sync.
- Five primitives.
queryfor reads,commandfor actions,streamfor live output,eventfor main-to-renderer pushes,defineStorefor shared state. - React hooks built in.
conveyor.window.init.useQuery(),conveyor.web.openUrl.useMutation(),conveyor.window.onFocusChange.useEvent(cb), all powered by TanStack Query, with query keys derived from the call path instead of written by hand. - State shared across windows. Main owns the state, every window stays in sync, and persistence to disk is opt-in.
- Handlers know their window. Each call carries the calling window as context, so titlebar and menu commands act on the right window without passing IDs around.
- Multi-window ready. A built-in window manager tracks open windows and lets any handler open a new one.
- Validated at the boundary. Zod schemas check every payload crossing the bridge, so bad input fails in main rather than deeper in your code.
- Middleware. Attach it to reusable bases and narrow the context for everything below it.
- Errors with codes. Failures cross the bridge with a stable code, so the renderer branches on
err.codeinstead of parsing messages. - Per-call timings in dev.
devLoggerlogs every IPC call while developing and is a no-op in packaged builds. - A preload that never changes. Two lines to expose the bridge, and it stays that way as your API grows.
App shell and UI
- Minimal by default. A window, titlebar, menu, theming, and the IPC bridge. Nothing to delete before you start.
- Playground on the
demobranch. Every primitive shown live, built onmainso it stays current. - Welcome screen you can remove. One folder (
app/components/welcome), nothing else imports it, and it registers no IPC of its own. - Custom window frame and titlebar. App icon, window controls, and a menu system with keyboard shortcuts on Windows, macOS, and Linux.
- Full titlebar menu, wired up. Undo, redo, cut, copy, paste, select all, zoom, fullscreen, reload, and devtools, all through typed commands.
- Smooth theme switching. The window cross-fades between light and dark instead of snapping colour by colour.
- A real error screen. The message first, React's component stack next to the error stack, dependency frames dimmed, and copy, retry, and reload buttons.
- Fonts and components refreshed. Geist and JetBrains Mono bundled, shadcn components updated onto the single
radix-uipackage, framer-motion dropped.
Platform and security
- Sandboxed renderer.
sandbox: trueout of the box, with the conveyor bundled into the preload so it works in a sandbox. - Working
safeStorageon Linux. The keychain backend is named explicitly, so secrets are encrypted on desktops Chromium does not recognise instead of silently falling back to plain text. - Hardened external links.
openExternalacceptshttp(s)URLs only.
Tooling
- Checks.
npm run typecheck,npm run lint:check, andnpm run format:check. - CI on every push. Verified on
main, then built and packaged on Linux, macOS, and Windows. - ESLint config in TypeScript.
eslint.config.ts, with the flat config format. - Consistent filenames. Every component file is kebab-case.
Also included
res://protocol for loading local resources.- Import path aliases:
@/app/,@/lib/,@/conveyor/,@/resources/. - Vite HMR for near-instant reloads in development.
- VS Code debugging preconfigured for both the main and renderer processes.
- electron-builder set up for Windows, macOS, and Linux packaging.
Breaking changes
useConveyor()is gone. Calls go through the typed client instead:conveyor.window.minimize(),conveyor.window.init.useQuery().- The IPC surface moved to
conveyor/:init.ts,modules/,router.ts,client.ts. Feature modules are main-process only, and the renderer imports justtype AppRouter.