Prerequisites
- A Mellowtel account and configuration key (get yours from the dashboard).
- An Electron application with access to the main process.
Installation
1. Install the Package
From your project root, install the Electron SDK:2. Add to Your Code
In your Electron main process file (typicallymain.ts or main.js), import the SDK, optionally call setupMellowtelApp() before the app is ready, instantiate Mellowtel with your configuration key, request consent from the user, and then call init() to start the service.
Replace
YOUR_CONFIGURATION_KEY with the key from your Mellowtel dashboard.new Mellowtel(configurationKey, options?)instantiates the SDK. The only option available today isdisableLogs, which defaults totrue. Set it tofalsewhile integrating so you can see connection state and request activity in your terminal.requestConsent(window, incentive)renders a native Electron message box anchored to theBrowserWindowyou pass in. The second argument is the dialog’s prominent headline (for example,"Get 3 months free"), shown above a fixed explanation of what Mellowtel does. It resolves totrueif the user accepts,falseif the user declines or closes the dialog, andundefinedif consent is already on file. The SDK persists the opt-in decision automatically, so you do not need to calloptIn()afterwards.init()throws only whenconfigurationKeyis empty. If the user has not opted in, it logs and returns silently. Otherwise it opens a WebSocket to Mellowtel’s backend. The call is non-blocking for renderer UI, so windows stay responsive while the connection is established.
Preventing system dialog interruptions (recommended)
The SDK ships with an optional helper,setupMellowtelApp(), that configures Electron command-line flags to suppress system dialogs (autofill popups, translation bars, NTLM / Kerberos auth prompts, password manager integration, media overlays, first-run dialogs) that would otherwise interrupt your users when Mellowtel’s hidden windows process requests in the background.
Call it at the top of your main process file, before app.whenReady(), and import it alongside the default export from mellowtel-electron. See the upstream README for the canonical usage.
User Consent
You have two paths for handling consent:- Use the built-in native dialog via
requestConsent(window, incentive). This is the fastest path and is what the snippet above shows. It renders a native Electrondialog.showMessageBoxwith your incentive copy as the headline and persists the user’s decision automatically. - Build your own consent UI and drive the SDK through
optIn(),optOut(), andgetOptInStatus(). Use this if you want custom branding, richer explanations, or localization beyond what the native dialog offers.
What your consent dialog must include
1
Explain what Mellowtel does
Use plain language. Example: “This app uses Mellowtel to share your unused internet bandwidth. In return, you get [benefit/feature]. You can opt out at any time in settings.”
2
Give users a clear choice
Include distinct Accept and Decline options.
3
Link to policies
Include links to the Terms of Service and Privacy Policy.
Let users change their consent later
Mellowtel provides a built-in settings dialog viashowConsentSettings(window). It renders a native dialog with Opt In / Opt Out buttons that match the user’s current state, and internally calls optIn() or optOut() (plus reconnecting the WebSocket on opt-in) when the user toggles. Wire it up to a menu item or settings button in your app so users can revisit their choice.
If you prefer to build your own settings screen, call getOptInStatus() to read the current state and optIn() / optOut() to change it.
Method Reference
TheMellowtel class exposes the following public methods. All are available on the instance you created with new Mellowtel(configurationKey, options?).
Lifecycle
init(): Promise<void>starts the service if the user has opted in, or silently returns early if not. Throws only when the configuration key is empty.shutdown(): Promise<void>cleans up SDK resources when the application is closing. Closes the WebSocket, destroys hidden worker windows, and clears background timers. Preserves the user’s opt-in preference.requestConsent(window: BrowserWindow, incentive: string): Promise<boolean | undefined>shows the built-in native consent dialog and persists the result. Returnstrueon accept,falseon decline or close,undefinedif consent was already given.showConsentSettings(window: BrowserWindow): Promise<void>shows the built-in manage-consent dialog. The SDK handles the opt-in / opt-out transitions internally when the user toggles their choice.
optIn(): Promise<void>flags the user as opted in without showing a dialog. Use this only after collecting consent through your own UI.optOut(): Promise<void>flags the user as opted out and performs full cleanup (same resources asshutdown(), plus clearing the saved consent preference). There is no need to callshutdown()afterward.getOptInStatus(): boolean | undefinedreturns the current opt-in state, orundefinedif the user has never made a choice.getNodeId(): stringreturns the Mellowtel node identifier for this installation. Useful when filing support tickets.
electron-store and survive app restarts. Surface them in your own UI if you want to show users the impact of their opt-in.
getTotalRequestCount(): numberreturns the total requests processed since install.getDailyRequestCount(): numberreturns the number of requests processed today.getRequestCountForDate(date: string): numberreturns the count for a specificYYYY-MM-DDdate.getDailyRequestsHistory(): { [date: string]: number }returns every daily count as a map.getRequestCountsInRange(startDate: string, endDate: string): { [date: string]: number }returns counts for a date range.getRequestCounts(): { total: number; daily: number; dailyHistory: { [date: string]: number } }returns all three counters in one call.
Lifecycle and app shutdown
After processing its first request, Mellowtel may create hidden Electron worker windows. Host applications must callshutdown() when the application is actually closing.
shutdown():
- Closes the WebSocket connection.
- Destroys hidden worker windows.
- Clears background timers and network resources.
- Preserves the user’s opt-in preference.
Single-window applications
Callshutdown() when the main application window closes:
window-all-closed event because Mellowtel’s hidden worker windows may prevent it from firing.
Tray applications
Do not callshutdown() when merely hiding the window to the system tray. Call it from the explicit Quit action:
macOS applications
If the application remains active after its windows close, callshutdown() only when the user actually quits the application.
Opting out
optOut() already performs full cleanup:
shutdown() afterward. Unlike shutdown(), optOut() also changes the saved consent preference.
Starting again
Aftershutdown() or optOut(), Mellowtel can be started again:
Consent Persistence
Opt-in state is stored in the platform-defaultelectron-store config path:
- macOS:
~/Library/Application Support/<YourAppName>/config.json - Windows:
%APPDATA%\<YourAppName>\config.json - Linux:
~/.config/<YourAppName>/config.json
Troubleshooting
"Package not found" error during install
"Package not found" error during install
- Confirm you are installing
mellowtel-electron(not a scoped GitHub Packages name). - Clear the npm cache and retry by running
npm cache clean --forcefollowed bynpm install mellowtel-electron.
The consent dialog never appears
The consent dialog never appears
- Make sure you call
requestConsentafterapp.whenReady()has resolved and with a valid, non-destroyedBrowserWindowreference. - If you use
setupMellowtelApp(), verify it is called beforeapp.whenReady(), not after.
"init() runs without errors but nothing happens"
"init() runs without errors but nothing happens"
This is by design.
init() silently returns early when the user has not opted in. Check getOptInStatus() to confirm. If it returns undefined or false, run requestConsent first. Note that the internal “User is not opted in” log is swallowed when disableLogs is left at its default (see “Logs are silent” below), so the terminal gives you no signal either way until you flip that flag.Logs are silent
Logs are silent
The
disableLogs constructor option defaults to true. Pass { disableLogs: false } as the second argument to the constructor while integrating to surface connection state and request activity in your terminal. This is also the fastest way to distinguish a “not opted in” silent no-op (see above) from a real connection failure.Estimated time to complete: 10-15 minutes. If you need help or have feedback, contact us at info@mellowtel.com or join our Discord community.