100% Local-First β’ GNU AGPLv3 Free Software
Ember is an implementation of Emotional Computing Systems β a class of cognitive software built on computational emotional mechanics.
Entries exist on a glowing timeline: newest ones burn bright, older ones cool to ash. Some are sealed until a future date. Others are written to disappear. Everything stays on your device. No accounts. No cloud. No tracking.
β If Ember resonates with you, please star the repository. Stars are how people find work like this, and it is the one thing that helps most.
Text Input and Saving mechanics.
The timeline β newest entries burn bright, older ones cool to ash.
Writing β paste is disabled, so it has to be in your own words.
Ember introduces three emotional mechanics that have not existed previously in software engineering:
- Emotional Decay β Emotional intensity reduces over time, encouraging raw expression without fear of digital permanency.
- Time-Lock Revisitation β Emotional entries cannot be deleted or edited until revisited, confronting avoidance and anchoring emotional memory.
- Honesty Constraints β Prevents self-editing and filtering during emotional expression, reducing cognitive distortion.
These mechanics form the foundation of Emotional Computing System, a category created and formally defined through Ember's architecture and whitepaper.
Ember processes all emotional data entirely offline.
- No Cloud Execution: No external servers, no synchronization.
- No Tracking: No telemetry, analytics, or behavioural logging.
- Free Software Guarantee: Licensed under GNU AGPLv3 to ensure long-term user autonomy and data sovereignty.
Your emotional state never leaves your device.
These guarantees describe Ember as you run it yourself β the desktop app, or the dev server on your own machine. The live demo is a separate static page: it keeps these properties (it has no backend at all), but it only shows the mechanics, it is not the full application.
- All data lives in browser IndexedDB β nothing leaves your machine
- Time-Lock encryption: AES-GCM 256-bit with PBKDF2 (200,000 iterations, SHA-256)
- The passphrase is derived from the unlock date and is never stored
- Spotify is entirely optional and uses PKCE OAuth (no client secret)
| Type | Mechanic | Description |
|---|---|---|
| Regular | β | Rich text entry, lives forever |
| Time Capsule | Time-Lock Revisitation | AES-256 encrypted and sealed until a date you choose β completely unreadable until then |
| Decaying | Emotional Decay | Fades word-by-word or burns down in opacity over days or weeks, leaving only a tombstone |
Type / on any line to open the block menu β pick a heading, quote, list, divider, or
link without leaving the keyboard.
Drag-and-drop images, PDFs, or any file onto an entry. Images render inline; PDFs open in-browser. Attachments inside Time Capsules are encrypted alongside the text.
Connect your Spotify account to save the track playing while you write. The song is stored permanently with the entry, and its audio energy/mood subtly tints the card colour on the timeline.
Ember implements Emotional Computing Systems as working software rather than describing them in the abstract. The terminology, the mechanics and the computational model are all defined by the code: the emotional mechanics, the validation loops and the local-first design are specified concretely enough to be reimplemented or built on.
The full technical framework is documented in the whitepaper:
"Emotional Computing System: A Technical Framework for Computational Emotional Mechanics."
| Layer | Role |
|---|---|
| Frontend Layer | Electron + JavaScript β emotional input interface and decay visualisation |
| Validation Engine | Emotional state validation, honesty constraints, and time-lock enforcement |
| Reflective Modules | Non-interpretive reflective processing and revisitation tooling |
| Storage Model | 100% local-first, encrypted storage |
| Layer | Technology |
|---|---|
| UI | Vanilla JavaScript (no framework) |
| Bundler | Vite 5 |
| Desktop | Electron 29 |
| Validation engine | C# / ASP.NET Core (services/validation-engine) |
| Reflective modules | Python / FastAPI (services/reflective-modules) |
| Storage | IndexedDB (local, no server) |
| Encryption | Web Crypto API β AES-GCM 256-bit, PBKDF2 200k iterations |
| Fonts | Cormorant Garamond Β· Lora Β· Kalam (Google Fonts) |
The validation engine and reflective modules described in the architectural
model are real, separate local processes β both bound to 127.0.0.1 only,
never reachable from outside the machine, and required for the app to run
(there is no in-process JS fallback):
- Validation engine (C#),
http://127.0.0.1:8901β validates a draft entry's capsule/decay settings before it's saved, and enforces the Time-Lock Revisitation gate (whether an entry may currently be edited or deleted). - Reflective modules (Python),
http://127.0.0.1:8902β computes Emotional Decay: how far an entry has decayed, and the redacted or fading text shown for it.
Honesty Constraints (disabling paste while writing) stay enforced in the frontend β there's no way for a backend to tell, after the fact, whether text was typed or pasted.
Prerequisites: .NET SDK 10+ and Python 3.11+, in addition to Node.
npm install
pip install -r services/reflective-modules/requirements.txt
npm run services # starts both local services on their ownThe desktop app starts the services itself, so npm run electron is all you
need there. npm run dev (the browser version) has no Electron to do that, so
it starts them alongside Vite.
If either service isn't running, Ember shows an error screen naming which one it can't reach rather than starting in a degraded state.
These prerequisites are for running from a checkout. Installed builds carry both services inside them β see Building installers β so end users need nothing but the app.
https://emberdemo-1.vercel.app/
An interactive page showing the three mechanics β drag a slider to watch an
entry decay, step through the time lock, and try to paste into the editor. It
runs entirely in the browser: no services behind it, and nothing typed on the
page is sent anywhere. Source in demo/.
An installed Ember bundles both services, so nobody needs .NET or Python to run it. Those toolchains are needed only on the machine doing the build.
npm install
pip install pyinstaller
npm run dist # builds the app, both services, and an installernpm run dist runs three steps in order:
| Step | What it produces |
|---|---|
vite build |
the frontend, into dist/ |
npm run build:services |
both services as standalone binaries, into build/services/ |
electron-builder |
the installer, into release/ |
The service binaries are copied into the packaged app's
resources/services/, which is where electron/services.cjs looks for them.
On launch it starts both, waits for each to answer /health, and stops them
again when the app quits. If a service will not start, Ember shows a window
naming it rather than an empty screen.
Running from a checkout, those binaries do not exist, so the same code falls back to running the services from source β which is why the prerequisites above still apply for development.
Targets are AppImage on Linux, dmg on macOS and NSIS on Windows. Each has to be built on its own platform, because the bundled services are native executables.
npm install
npm run devOpen http://localhost:5173 in your browser.
npm install
npm run electronWindows: If Electron's binary fails to download, use
npm run devinstead β the browser version is fully featured.
Ember can save the track playing while you write. Click β« in the top-right and choose Sign in with Spotify β that is the whole thing.
Using the browser version, open it at http://127.0.0.1:5173, not
localhost:5173. Spotify only accepts the loopback address in redirect URIs, and the two are different origins, so signing in fromlocalhostloses the verifier stored for127.0.0.1.
"Sign in with Spotify" needs one Spotify application to exist, registered once
by whoever ships Ember. Until DEFAULT_CLIENT_ID in src/spotify.js is filled
in, the panel asks each user for a Client ID of their own instead.
- Create an app at developer.spotify.com/dashboard
- Add both of these as Redirect URIs:
http://127.0.0.1:8888/callbackβ the desktop apphttp://127.0.0.1:5173/callbackβ the browser version (npm run dev)
- Copy the Client ID into
DEFAULT_CLIENT_IDinsrc/spotify.js
Committing that Client ID is safe. Ember uses the PKCE flow, which has no client secret precisely so the ID can ship inside a public application β the secret that matters is the code verifier, generated fresh on each machine for every sign-in and never transmitted.
Two things to know before relying on it:
- A new Spotify app starts in Development Mode, which only works for up to 25 accounts that you add by email in the dashboard. Going beyond that needs Spotify's Extended Quota Mode review.
- Anyone can still use their own app: Use your own Spotify app instead, in the same panel, overrides the shipped ID. Forks and self-hosters will want this, and it is what the panel falls back to when no ID is shipped.
βββ src/
β βββ app.js # Main UI β views, editor, event binding
β βββ crypto.js # AES-GCM encrypt/decrypt (text + binary)
β βββ storage.js # IndexedDB persistence
β βββ services.js # Client for the local validation-engine / reflective-modules services
β βββ spotify.js # Spotify PKCE OAuth + now-playing API
β βββ style.css # Coal & Fire design system
βββ services/
β βββ validation-engine/ # C# β entry validation, time-lock enforcement
β βββ validation-engine-tests/ # xUnit tests for the above
β βββ reflective-modules/ # Python β emotional decay computation
βββ electron/
β βββ main.cjs # Electron main process + Spotify OAuth window
β βββ preload.cjs # Context bridge (contextIsolation)
βββ index.html
βββ vite.config.js
βββ package.json
Ember establishes the foundation for a new generation of privacy-first emotional tools built on structured emotional computation. It demonstrates how emotional processes can be modelled through deterministic mechanics rather than interpretation, forming the basis of a new category in cognitive software.
If you find Ember interesting β the mechanics, the local-first architecture, or just the idea β star it on GitHub. It costs you a click, and it is what puts a project like this in front of the next person who needs it.
Jeremiah Ayeni β github.com/Jeremy-1011
Authorship is also recorded in the header of every source file, and shown in the
app's own About panel (the i button in the top-right of the window).
GNU Affero General Public License v3.0 or later β Copyright Β© 2026 Jeremiah Ayeni. See LICENSE for the full text.
In short, you are free to use, study, modify and redistribute Ember, including commercially, on these conditions:
- Keep it open. Any copy or modified version you distribute must also be released under the AGPL, with source available. You cannot take this code closed-source.
- Network use counts as distribution. If you run a modified Ember as a hosted service, you must offer its users the corresponding source code (AGPL Β§13). This is the clause the MIT licence lacked.
- Keep the notices. The copyright and licence notices must be retained.
The AGPL permits charging money for the software. What it does not permit is distributing it β or hosting it β without passing the same freedoms on.
Ember was released under the MIT licence up to and including commit
051eb92.
That grant is irrevocable for those versions: anyone who obtained the code
under MIT keeps MIT rights to that code. The AGPL applies from this commit
onwards. Relicensing was possible because all contributions to date are the
work of a single copyright holder.