Ellipsis
A message medium that records and replays how a message was actually
typed; hesitations, pauses, and abandoned sentences included, instead
of keeping only the final, cleaned-up text.
What It Is
Ellipsis is a place to compose and send typed performances. Writing in
the composer captures every insertion, deletion, and pause as a
timestamped recording, not just the final string of characters. Before
sending, you watch your own performance back and can cut any specific
false start you don’t want included, a deliberate consent step, not an
accidental leak of every private half-thought. You then send it, either
to a contact’s inbox or as an unlisted link that needs no account to
open. Whenever the recipient chooses to, they watch your message retype
itself at the pace it actually happened.
Why It Exists
Every mainstream text medium: SMS, email, chat apps, discards the
process of writing the instant you hit send. For emotionally weighted
messages (an apology, a confession, a hard truth, nerve-wracking good
news), that discarded process often carries as much meaning as the words
themselves. The closest existing products (Beam Messenger, Bop Me, POZZ)
show typing live while both people are online, nothing is recorded, and
nothing survives the conversation. Ellipsis is the opposite structurally:
compose alone, at your own pace, and produce a durable, replayable
artifact — sent the way you’d send a voice memo, not a live stream. Full
rationale and the existing-product research behind this: docs/product.md
and docs/product-selection.md.
Features
- A composer that transparently captures a full keystroke event stream
while you write, no separate “recording mode.”
- A deterministic replay engine with play / pause / scrub / skip-to-end,
and pause compression so a real multi-minute silence plays back as
clearly-longer-but-not-absurd rather than either vanishing or actually
taking minutes.
- A pre-send review step that detects every self-contained “abandoned
passage” (something typed and then fully undone) and lets you cut any
of them — a real edit to the stored recording, not a UI-only hide.
- Two ways to deliver: to a contact’s inbox by username, or as an
unlisted share link viewable by anyone who has it, no account required.
- Threaded correspondence, lightweight reactions, and two-step
confirmation on destructive actions (deleting a thread, revoking a
share link).
- A conversation model that stays strictly two-party: replying to a share
link only joins its thread if no one else already has: seesrc/app/api/share/[token]/reply/route.ts.
Screenshots
The landing page includes a real, working replay of an Ellipsis — the
clearest demonstration of the product is watching that play at
<https://ellipsis.fmrdigital.dev>.
Architecture
Next.js 14 (App Router, TypeScript) + PostgreSQL + Prisma, deployed as
two Docker Compose services. Full reasoning for every major decision —
including the keystroke-diffing capture mechanism, the redaction safety
invariant, and the deployment topology — is in docs/architecture.md.
Deployment
Runs on the designated development server (Scooby) via Docker Compose.
git clone https://forgejo.familytechlab.com/frank/ellipsis.git
cd ellipsis
cp .env.example .env # fill in a real POSTGRES_PASSWORD (and CLOUDFLARE_TUNNEL_TOKEN for public access)
docker compose up -d --build
Live at <https://ellipsis.fmrdigital.dev> via a Cloudflare Tunnel
(ellipsis-cloudflared), and also reachable directly on the LAN/Tailscale
at http://:4701. Postgres is not published to the host
at all — see docs/architecture.md, “Deployment topology,” for the full
exposure history and reasoning.
docker-entrypoint.sh runs prisma migrate deploy before starting the
server, so a normal docker compose up -d after a git pull picks up
any new migration automatically.
Configuration
All configuration is in .env (see .env.example):
| Variable | Purpose |
|—|—|
| POSTGRESUSER / POSTGRESPASSWORD / POSTGRESDB | Database credentials, used by both containers. |
| DATABASEURL | Only needed for local (non-Docker) development. |
Operations
docker compose up -d --build # build and (re)start
docker compose down # stop and remove containers (data persists in the named volume)
docker compose logs -f app # tail application logs
docker compose restart app # restart just the app
npm test # run the unit test suite (locally, not in the container)
Backup and Restore
See docs/backup.md. In short: scripts/backup.sh andscripts/restore.sh wrap pg_dump/psql against the runningellipsis-postgres container.
Development
Requires Node 18+ and a local or reachable PostgreSQL instance.
npm install
cp .env.example .env # set DATABASE_URL to a real Postgres
npx prisma migrate deploy
npm run dev # http://localhost:3000
Testing
npm test
30 unit tests cover the parts of the system with real logic and real
failure modes: the keystroke diff/replay engine (src/lib/ops.ts,src/lib/replay.ts) and the redaction safety invariant
(src/lib/redact.ts) — including the case that was actually caught and
fixed during development: a naive redaction that would have silently kept
part of an “abandoned” passage’s content instead of removing it. UI
correctness, the full send/receive/reply flow, share-link privacy, and
persistence across a full container teardown were verified directly
against the running application (desktop and a real emulated mobile
viewport) — see docs/completion-report.md for the full account.
Ellipsis is a product of FMR Digital LLC © 2026 FMR Digital LLC · All rights reserved.



