Skip to content

Neonsy/Electron-Base

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Electron + Vite + React Template

A security-conscious Electron application base with React 19, Vite 8, TypeScript 6, tRPC over sandboxed IPC, TanStack Router and Query, Tailwind CSS 4, cross-platform installers, opt-in local database and E2E scaffolds, and a complete stable/beta release path.

The repository is intentionally opinionated about reproducibility and releases:

  • Node.js is pinned to 24.18.0 LTS.
  • pnpm is pinned to 11.10.0; the packageManager field also carries an integrity hash.
  • Dependency install scripts use pnpm 11's explicit allowBuilds policy.
  • Windows, macOS, and Linux packages are built on native operating-system GitHub-hosted runners.
  • GitHub Releases hosts update artifacts for a stable channel and an opt-in beta channel.
  • A manual workflow validates the version, builds every configured OS and architecture target, and publishes only after the complete artifact set exists.

Prerequisites

  • Node.js 24.18.0 LTS
  • pnpm 11.10.0 installed as a normal developer tool
  • Platform build tools when packaging locally
npm install --global pnpm@11.10.0
pnpm --version

The final command must print 11.10.0. A standalone pnpm installation is the normal local workflow; Corepack remains optional for developers who prefer it. The packageManager, engines, .node-version, .nvmrc, workspace policy, and release workflow all enforce the same runtime baseline, while CI installs pnpm through pnpm/action-setup.

Quick start

pnpm install
pnpm dev

The development command starts Vite and Electron together. The renderer uses hash routing so packaged file:// URLs work without a web server.

Run the complete local validation suite with:

pnpm check

Scripts

Command Purpose
pnpm dev Start Vite and Electron in development mode
pnpm build Generate routes and build renderer, Electron main, and preload bundles
pnpm build:win Build the app and a Windows x64 NSIS installer
pnpm build:mac Build macOS DMG, PKG, and ZIP outputs for x64, arm64, and universal
pnpm build:linux Build Linux AppImage, DEB, and RPM outputs for x64, arm64, and armv7l
pnpm typecheck Generate routes and type-check renderer and Node/Electron projects
pnpm lint Generate routes and run the type-aware ESLint configuration
pnpm lint:fix Apply safe ESLint fixes
pnpm format Format the workspace with Prettier
pnpm format:check Check formatting without changing files
pnpm test Run the Vitest suite once
pnpm test:watch Run Vitest in watch mode
pnpm test:e2e Build and launch the Playwright Electron E2E spec
pnpm db:generate Generate committed SQLite migrations from the product schema
pnpm db:check Check the Drizzle migration history for consistency
pnpm check Run typecheck, lint, format check, tests, and the production bundle

There is deliberately no publish script. Releases go through the auditable, native-runner workflow in .github/workflows/release.yml.

pnpm check validates the Drizzle migration history and discovers the Playwright spec, but it does not launch a GUI. Run pnpm test:e2e explicitly on a desktop test host; it builds first, launches Electron with an isolated user-data directory and updates disabled, and closes the application in cleanup.

ESLint composes the recommended type-aware TypeScript, React, React Hooks Compiler, JSX accessibility, import, Node, security, TanStack Query, Vitest, and Playwright policies. Narrow exceptions are documented beside reviewed runtime boundaries. Prettier is the single formatting authority and its Tailwind plugin points at the Tailwind CSS v4 stylesheet, so project theme utilities participate in deterministic class sorting.

Architecture

React renderer
  └─ electron-trpc renderer link
       └─ sandboxed CommonJS preload (only the tRPC bridge is exposed)
            └─ typed IPC handler in the Electron main process
                 ├─ tRPC application routers
                 ├─ window/security policy
                 ├─ structured logging
                 └─ update controller

The key boundaries are:

  • src/: browser-only React renderer code.
  • electron/main/: privileged Electron lifecycle, windows, security, logging, and updates.
  • electron/backend/trpc/: the typed API exposed to renderer windows over IPC.
  • electron/main/preload/: the minimal sandbox-compatible bridge.
  • vite.config.ts: renderer, main-process, and preload bundling.
  • electron-builder.config.ts: installers, updater provider, architectures, and artifact names.

Import aliases make the runtime boundary visible:

  • @/web/* resolves to src/*.
  • @/app/* resolves to electron/*.

Do not import Electron or Node APIs into renderer modules. Add privileged behavior behind a narrow tRPC procedure.

Adding an IPC procedure

  1. Put domain behavior in a focused module under electron/backend/trpc/routers/ or a main-process service.
  2. Register a query or mutation in the appropriate router.
  3. Validate every renderer-controlled input at the router boundary.
  4. Call the inferred procedure through trpc hooks or the vanilla client in src/lib/trpcClient.ts.
  5. Add a behavior test when the procedure protects a meaningful failure, security, or persistence path.

The renderer never receives raw ipcRenderer, filesystem access, arbitrary update feeds, or other broad capabilities.

External links

Use a normal link when renderer content should open documentation or another public URL in the system browser:

<a href='https://example.com' target='_blank' rel='noreferrer'>
    Open documentation
</a>

The main-process navigation guard denies the new Electron window, accepts only well-formed http:, https:, and mailto: URLs, and passes accepted URLs to shell.openExternal(). It also intercepts attempted in-window external navigation. In production, only the exact packaged index.html entry may retain the preload bridge; unrelated local file: documents are blocked along with remote in-window navigation. Do not expose Electron shell or an unrestricted URL-opening IPC procedure to renderer code; extend the central protocol/origin policy if a product genuinely needs another scheme.

Update channels: what is actually supported

Three different systems are easy to conflate:

  1. Electron's built-in autoUpdater has no named channel abstraction. It accepts a feed and supports macOS and Windows; it does not provide a canary/beta/stable enum.
  2. This template uses electron-updater, which adds Linux, GitHub provider integration, generated metadata, download progress, signing checks, and ordered latest, beta, and alpha channel semantics.
  3. GitHub Releases exposes draft, prerelease, and full-release states. GitHub does not natively label a release as canary, beta, or alpha.

The template intentionally exposes two product choices:

User choice Provider channel Receives
Stable latest Stable releases only
Beta beta Beta releases, then stable

canary is not an alias for beta. The unused alpha tier and arbitrary custom identifiers are excluded so the template has one predictable prerelease cohort.

An accessible Stable/Beta control is prepared in src/components/updates/update-channel-control.tsx, but it is not mounted on the template overview while the provider still points at an example repository. Mount it in product settings after configuring a real update feed. The main process validates and atomically stores the choice in update-channel.json below Electron's per-user userData directory. A beta build defaults to Beta only when no preference exists; stable builds default to Stable. A stored choice always wins.

Switching back to Stable never permits a downgrade. If the installed beta is newer than the latest stable release, the app waits until a higher stable version exists. This avoids rolling local data back across forward-only migrations.

Updater checks are disabled in unpackaged development by default. UPDATER_ENABLED=1 enables the code path for UI testing, but a valid dev-app-update.yml is also required. Installed update behavior must ultimately be tested with a signed packaged application.

GitHub update provider

package.json deliberately contains this example repository:

https://github.com/example-owner/example-electron-app

Replace the example owner and repository before releasing. electron-builder.config.ts reads that URL as the source of truth for the GitHub provider, and the release preflight fails if the placeholder remains or does not match the repository running the workflow. The app must use a public update repository; never embed a GitHub token in a desktop binary.

GitHub publishing does not infer the update channel from a prerelease version. The builder therefore requires an explicit UPDATE_CHANNEL and verifies it against package.json.version:

  • 1.4.0 must build with UPDATE_CHANNEL=latest.
  • 1.5.0-beta.1 must build with UPDATE_CHANNEL=beta.

Normal local builds infer the same channel from the package version. Alpha, canary, RC, build-metadata, and malformed versions fail before packaging.

Cross-platform packages

Platform Architecture targets Outputs for each target Primary files
Windows x64 NSIS per-user installer 1
macOS x64, arm64, and universal DMG, PKG, and the required updater ZIP 9
Linux x64, arm64, and armv7l AppImage, Debian DEB, and RPM package 9

Artifacts are written to release/{version}/ and use URL-safe names containing platform and architecture. The three macOS ZIPs are updater payloads rather than installers; electron-updater requires ZIP payloads for macOS updates. The matrix therefore contains 19 primary files: 16 direct packages/installers and three updater ZIPs. Manifests, blockmaps, and SHA256SUMS.txt are additional release assets. The release preflight verifies every expected architecture-specific filename and every filename referenced by update metadata before publication.

electron-builder uses platform-native architecture tokens in filenames: Linux x64 is x86_64 for AppImage/RPM and amd64 for DEB; arm64 RPM is aarch64; and armv7l DEB metadata reports armhf. Update metadata is also architecture-aware: Windows and macOS each use one channel manifest, while Linux produces separate x64, arm64, and ARM manifests.

These are the generic direct-download formats that can be configured honestly in a reusable template. Other builder targets need their own product decisions:

Target family Why it is not in the default release
MAS / MAS development Requires App Sandbox behavior, entitlements, provisioning profiles, Store identities, and Store updates
Snap Requires confinement/plugs, Snapcraft infrastructure, and a separately owned Snap Store release path
Flatpak Requires a pinned runtime/SDK, product-specific permissions, and a Flathub or owned repository plan
Pacman Electron Builder currently labels the target beta; add only with an Arch install/start test
APK / FreeBSD / P5P Requires target-runtime compatibility work rather than packaging an untested Electron binary
ZIP, 7z, and tar files Archives are useful for custom distribution but are not installers

Use the platform-specific script on its native operating system. The workflow uses windows-2025, macos-15, and ubuntu-24.04 runners; its ARM Linux outputs are architecture-cross-packaged because GitHub does not provide an armv7l hosted runner. This template currently has no native Node addon, so builder can assemble those outputs, but that is not a runtime compatibility test. Before claiming production ARM support, install and launch arm64 and armv7l packages on real target systems. Any native addon requires per-architecture rebuilds and tests.

Electron 43 is the final Electron line that publishes Linux armv7l binaries and reaches end of support in January 2027. Upgrading to Electron 44 or later requires deliberately removing the armv7l target.

The baseline avoids Windows ARM in the shared GitHub feed. The current Windows updater metadata is not architecture-qualified, so a mixed x64/ARM feed needs a deliberate separate-feed design before it is safe to advertise.

The NSIS uninstaller preserves application data by default. Products that want an explicit “remove my data” action should implement and confirm it in the UI rather than silently deleting user data on uninstall.

Signing

Unsigned packages are useful only for template development. Production releases should configure:

  • Windows Authenticode signing (WIN_CSC_LINK and WIN_CSC_KEY_PASSWORD, or an intentionally designed Azure signing integration).
  • macOS Developer ID signing (MAC_CSC_LINK and MAC_CSC_KEY_PASSWORD).
  • macOS PKG signing with a separate Developer ID Installer certificate (MAC_INSTALLER_CSC_LINK and MAC_INSTALLER_CSC_KEY_PASSWORD).
  • macOS notarization (APPLE_API_KEY_BASE64, APPLE_API_KEY_ID, and APPLE_API_ISSUER).

macOS auto-update requires a signed app. The workflow treats these secrets as optional so a newly generated template can exercise packaging, but a real product should make missing signing credentials a release-preflight failure.

Manual release workflow

The workflow is manually dispatched with exactly one tag input:

vMAJOR.MINOR.PATCH
vMAJOR.MINOR.PATCH-beta.NUMBER

Examples:

  • v1.4.0 creates a full stable release and latest update metadata.
  • v1.5.0-beta.1 creates a GitHub prerelease and beta update metadata.

The workflow rejects leading zeroes, beta number zero, other prerelease names, build metadata, a package/tag mismatch, an existing tag, the example repository URL, or a run that is not dispatched from the default branch.

It then:

  1. Installs the pinned toolchain from the frozen lockfile and runs repository validation.
  2. Runs the real production Electron-window smoke test on each operating-system runner; Linux uses Xvfb.
  3. Builds independently on three native operating-system runners with publishing disabled and no release token.
  4. Uploads short-lived workflow artifacts.
  5. Waits for approval on the protected release environment.
  6. Verifies all 19 primary files, five channel manifests, and every referenced updater payload; rejects filename collisions; and creates SHA256SUMS.txt.
  7. Creates the tag at the validated commit and publishes the complete GitHub release in one final write.

This single-writer design avoids half-published releases when one platform fails. See docs/RELEASING.md for repository settings, signing, promotion, hotfixes, and recovery.

Versioning, merge strategy, and patch notes

Keep the protected default branch releasable and use short-lived branches. The recommended repository settings are:

  • Pull requests required, with review, successful checks, and resolved conversations.
  • Squash merging only, using the pull request title as the squash commit title.
  • Linear history; no force-pushes or branch deletion.
  • A merge queue only when repository traffic makes it worthwhile.

Each user-visible pull request adds a concise entry under [Unreleased] in CHANGELOG.md. A release pull request sets the exact package version, moves those entries into a dated version section, and restores an empty Unreleased section. GitHub's generated notes add categorized pull requests and contributors; the curated changelog remains the source for highlights, migrations, and operational warnings.

Promote a line as 1.5.0-beta.11.5.0-beta.21.5.0. Fix stable defects with a higher patch such as 1.5.1. Never move tags or replace published assets. If a release is bad, fix forward with a higher version because some clients may already have installed it.

pnpm 11 policy

pnpm-workspace.yaml contains the pnpm 11-native policy:

  • allowBuilds explicitly permits reviewed Electron/esbuild-related dependency scripts. The removed pnpm 10 onlyBuiltDependencies setting is not used.
  • nodeVersion and engineStrict prevent resolving dependencies incompatible with Node 24.18.0.
  • A 24-hour minimum release age makes pnpm 11's dependency quarantine explicit while retaining its non-strict fallback for packages that have no older satisfying version.
  • Exotic transitive sources and unreviewed dependency build scripts retain pnpm 11's secure defaults.

If pnpm reports a new dependency build script, inspect the package and version before adding a precise true or false entry to allowBuilds. Never enable every dependency script globally.

The committed lockfile remains the reproducible dependency source. CI uses pnpm install --frozen-lockfile; update it only through the pinned pnpm release.

The exact 11.10.0 pin is deliberate. During this migration, pnpm 11.11.0 was tested against the same clean graph and exited successfully before writing either the lockfile or node_modules; 11.10.0 completed the install and then passed a frozen reinstall. Treat a future pnpm bump as a tested toolchain change, not an automatic version edit.

Security baseline

  • Renderer context isolation and Chromium sandboxing are enabled.
  • Node integration is disabled in the renderer.
  • The preload is a single CommonJS sandbox bundle exposing only tRPC.
  • Navigation and window.open requests are allowlisted and external links open in the OS browser.
  • A centralized production CSP blocks inline scripts, plugins, framing, and arbitrary connections.
  • Production devtools are disabled.
  • Package-time Electron fuses disable ELECTRON_RUN_AS_NODE, Node option/inspector injection, encrypt Chromium cookies, and require the integrity-checked ASAR on Windows and macOS.
  • Structured logs are stored below Electron userData, batched, retried, and flushed on shutdown. evlog 2 redacts production events before drains by default.
  • Update feed selection cannot be set to an arbitrary URL or channel by the renderer.

These defaults reduce risk; they do not replace a product-specific threat model, dependency review, code signing, secure secret handling, or testing on every supported operating system.

One deliberate compatibility exception remains: the packaged renderer currently uses file://, so the grantFileProtocolExtraPrivileges fuse stays enabled. Before handling untrusted content or shipping a high-risk product, migrate local assets to a privileged custom protocol, test navigation/CSP on every platform, and only then disable that fuse.

Optional ecosystem guide

This base installs only two deliberately inert, commonly useful exceptions: a Node SQLite + Drizzle scaffold and a single Playwright Electron spec beside the Vitest suite. It does not install a hosted backend, auth vendor, analytics SDK, sync engine, settings library, crash reporter, or native SQLite addon without a product requirement. Those choices define data ownership, retention, deletion, consent, offline behavior, credentials, native build risk, and operating cost. The shortlist below was rechecked against primary documentation on 2026-07-11; recheck compatibility and release age when adopting one.

Product need Recommended first look Why and guardrail
Local relational data Drizzle ORM + Node's node:sqlite Typed schemas and committed migrations without an ABI-bound addon. Node 24 calls node:sqlite release-candidate quality; isolate sustained synchronous work from the main event loop.
Realtime hosted backend Convex Strong typed functions and reactive subscriptions. It is a hosted architecture choice, not a durable offline mutation queue; add an idempotent local outbox and reconciliation when offline-first writes matter.
Small non-secret preferences electron-store Atomic, schema-validated JSON for settings. It rewrites the whole file, is not a database, and its encryptionKey is obfuscation rather than secret protection.
Tokens and local secrets Electron safeStorage Prefer the built-in asynchronous API from the main process. Account for key rotation, temporary provider failure, Windows same-user limits, and Linux fallback strength.
Desktop authentication Better Auth Electron A real Electron integration with system-browser PKCE, deep links, and Linux fallback. It requires a hosted Better Auth server; keep tokens/cookies in main-process storage and expose only sanitized session state.
Crash diagnostics Sentry Electron Covers main, renderer, and native failures. Decide consent, PII scrubbing, sampling, retention, release/channel tags, and CI-only source-map upload credentials before enabling it.
Product analytics and flags PostHog Use only with an explicit analytics need and consent/opt-out policy. Electron renderer builds must not load remote code; flags are never authorization, and queued events are not durable.
Reactive client collections TanStack DB A natural extension when normalized live queries, optimistic transactions, or a sync engine become necessary. It is still beta; TanStack Query remains the simpler default.
End-to-end desktop tests Included Playwright; WebdriverIO Electron service as an alternative The scaffold covers the production renderer and BrowserWindow security preferences. Playwright's Electron support remains experimental and does not intercept native dialogs; prefer WDIO instead when its packaged-app helpers materially help.
Native Node dependencies @electron/rebuild Add only when an ABI-bound addon is unavoidable. Rebuild after Electron upgrades and validate every OS/architecture in native CI; electron-builder already handles production dependency rebuilding during packaging.
Existing enterprise telemetry OpenTelemetry JS Prefer manual main-process spans and an owned Collector when the organization already uses OTLP. The Node SDK and browser instrumentation still carry experimental edges; do not duplicate a primary Sentry integration accidentally.

Other credible but more architectural paths include PGlite when local PostgreSQL semantics justify a WebAssembly database, and the ElectricSQL, PowerSync, RxDB, or TrailBase integrations described by TanStack DB when real offline-first synchronization is the actual product. Evaluate worker/CSP behavior, conflict policy, backend ownership, payload size, licensing, and recovery before choosing one. libSQL/Turso is another SQLite-sync family, but its native/prebuilt target matrix must cover every installer architecture before this template can advertise it.

Local data: the default recommendation

The checked-in electron/main/data/ scaffold is intentionally inert: normal startup does not import it, create a file, or invent product tables. openLocalDatabase() applies defensive mode, foreign keys, a bounded busy timeout, WAL, and disabled extension loading. Define ownership, cardinality, retention, export, reset, uninstall, corruption recovery, and forward-migration behavior before wiring it into a main-process service.

The official drizzle-orm/node-sqlite adapter is not present in Drizzle's current stable 0.45.2 package. The template therefore pins both drizzle-orm and development-only drizzle-kit exactly to the official 1.0.0-rc.4 line instead of hiding an unsupported adapter or adding an Electron ABI-bound SQLite addon. Re-evaluate that deliberate pre-release pin when Drizzle 1.0 becomes stable.

After defining product tables in electron/main/data/schema.ts, run pnpm db:generate, review and commit the numbered SQL, and keep pnpm db:check green. Generated SQL and metadata are packaged under resources/migrations; production code must apply migrations before normal data access and back up before risky changes. Never run drizzle-kit push against an end-user database. Store the database below app.getPath('userData').

Node 24.18.0's built-in SQLite avoids Electron ABI rebuilds, but DatabaseSync is synchronous. Short transactions can remain behind a narrow main-process tRPC service; imports, search indexing, and sustained queries should run in an Electron utilityProcess. Keep extension loading disabled unless a reviewed extension is essential.

better-sqlite3 remains a credible performance alternative, not this template's default. At the research snapshot its release declared Node 24 support but did not publish the Electron 43 ABI 148 prebuild, so it would require source rebuilding and native verification on the complete target matrix. Reconsider it when compatible prebuilds exist or benchmarks justify the operational cost. Neither electron-store encryption nor safeStorage transparently encrypts an entire SQLite database; full-database encryption needs its own threat model and maintained solution.

Cloud, auth, and telemetry

  • Convex is a good reactive cloud backend when collaboration is the product requirement. Public functions still need authorization, deployment/admin keys stay in CI, and the client must use safe offline defaults. A reconnecting client is not the same as a crash-safe local write queue.
  • Native desktop OAuth should use the system browser and Authorization Code with PKCE, never a client secret or an auth webview. Better Auth is the generic self-hosted option here because it has an official Electron integration; managed identity vendors remain product-specific evaluations.
  • Sentry is the first remote diagnostics option to evaluate. Upload source maps during the protected release pipeline, delete them from release artifacts, and keep its auth token out of the binary. Retain bounded local evlog diagnostics because cloud delivery is best-effort.
  • PostHog is for consented product analytics, cohorts, or flags—not crash reporting or authorization. OpenTelemetry is most sensible when an organization already owns an OTLP Collector and telemetry policy. Do not install all three.
  • For update observability, record discrete phases and durations rather than every progress tick. A product that needs install-success metrics should persist a minimal pending-update marker immediately before installer handoff, confirm it on the next successful startup, and avoid user data or private response bodies in that marker.

Testing and native integrations

Vitest remains the fast behavior-test baseline. The included Playwright spec builds the production bundles, launches the unflipped development Electron binary with isolated user data, and checks the real renderer plus hardened window preferences. pnpm check only performs safe test discovery; pnpm test:e2e is the explicit GUI run. Extend it for preload, deep-link, updater UI, and packaged-binary behavior as those become product requirements. Playwright's Electron launcher requires CLI inspection, so do not weaken production fuses to run it. If WDIO's stronger packaged-app helpers are more valuable, replace Playwright rather than maintaining two E2E stacks.

Native dependencies multiply platform, architecture, compiler, signing, and supply-chain work. Prefer Node/Electron built-ins such as node:sqlite, safeStorage, and utilityProcess. If a native addon is justified, review its prebuild matrix, add its install script explicitly to pnpm allowBuilds, rebuild for Electron, and exercise it on every native CI runner before claiming support.

The template already owns the common application-layer choices: ArkType validation, typed tRPC IPC, TanStack Router / Query / Form / Virtual, Zustand, neverthrow, evlog, Vitest, and electron-updater. Do not add Zod, Redux, electron-log, another updater, or a second result type by habit; replace an existing choice only when the migration solves a measured problem.

Project structure

.
├── .github/
│   ├── release.yml                 # Generated release-note categories
│   └── workflows/release.yml       # Manual native-runner release workflow
├── docs/RELEASING.md               # Maintainer release runbook
├── electron/
│   ├── backend/trpc/               # Typed IPC routers and context
│   └── main/
│       ├── bootstrap/              # Electron lifecycle orchestration
│       ├── data/                   # Inert node:sqlite + Drizzle scaffold
│       ├── logging/                # evlog setup and NDJSON drain
│       ├── preload/                # Sandboxed preload build and entry
│       ├── security/               # CSP and URL policy
│       ├── updates/                # Updater and persisted channel policy
│       └── window/                 # BrowserWindow factory and guards
├── e2e/                            # Explicit Playwright Electron test
├── scripts/release/                # Dependency-free release validation helpers
├── src/
│   ├── components/                 # Renderer UI and development tools
│   ├── lib/                        # Providers and tRPC clients
│   ├── pages/                      # Page implementations
│   ├── routes/                     # TanStack file routes
│   └── styles/                     # Tailwind theme and global styles
├── CHANGELOG.md
├── drizzle.config.ts
├── electron-builder.config.ts
├── package.json
├── playwright.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── vite.config.ts

Environment overrides

Copy .env.example to .env only for local overrides. Do not put credentials in Vite-prefixed variables or commit secrets. Signing and GitHub publication credentials belong in protected CI secrets/environments, not application environment files.

Customization checklist

Before building a real product:

  1. Replace the example repository URL, app ID, product name, author, homepage, bugs URL, icons, and UI copy.
  2. Review the runtime dependencies and remove demonstration libraries the product will not use.
  3. Extend the CSP only for explicitly required origins.
  4. Define persistence ownership, lifecycle, migrations, deletion, and recovery before enabling the inert database scaffold.
  5. Configure Windows signing and macOS signing/notarization.
  6. Protect the release environment and default branch, enable immutable releases, and create release-note labels.
  7. Install an older signed build on each supported OS/architecture combination and test stable, beta opt-in, beta-to-stable promotion, interrupted downloads, and fix-forward recovery.

License

MIT

About

This is my personal starting point for making modern Electron apps.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Contributors