Skip to content

About

save and sync per-chat draft messages across devices — mv3 browser extension + lsposed android module over a next.js + neon backend. works with messenger, discord, whatsapp and instagram dms.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

GlitchDraft logo

GlitchDraft

save drafts per conversation, keep them on every device
mv3 browser extension · lsposed android module · next.js + neon backend

MIT license latest release release workflow platforms backend android live demo

🧵 per-chat drafts
one row per conversation —
drafts never mix across chats
🔄 sync everywhere
start a reply on the phone,
finish it in the browser
🖼️ text + images
paste images into drafts too,
not just text
📱 android overlay
floating draft panel inside
the chat apps themselves
🕐 timestamps
created + modified times on
every card, on both platforms
🔌 bring your own backend
your next.js + neon, or the
legacy firestore path

supported surfaces

surface web extension android module
messenger ✅ ✅ (native)
facebook messages ✅ ✅ (in-app webviews)
discord ✅ ✅
whatsapp ✅ (web) ✅ (native)
instagram dm ✅ 🔧 hook landed, device test pending

chat ids are scoped per conversation (messenger_web_<fbid>_<name> vs messenger_android_<thread>_<name>, instagram_web_<thread>_<name>, …), and a name-slug matcher bridges the two sides so the same conversation resolves to the same drafts even though web and android derive ids differently.

how it works

flowchart LR
    A["web extension<br/>content.js + background.js"] -->|REST + x-api-key| C["next.js api<br/>/api/drafts/*"]
    B["android module<br/>OverlayController + DraftRepository"] -->|REST + x-api-key| C
    C --> D[(neon postgres)]
    A -.legacy.- E[(firestore)]
    B -.legacy.- E
Loading

both clients speak the same small REST API. sync polling runs on a 10-second tick and only while the panel/tab is visible, so an idle chat costs no backend compute.

quick start

browser extension (edge / chrome)

  1. grab the latest glitchdraft-<version>.zip from releases — every push publishes one — and unzip it (or clone the repo and use extension/ directly)

  2. open edge://extensions (or chrome://extensions), enable developer mode, load unpacked → pick the unzipped folder (or extension/)

  3. open a chat, click the extension icon or press Alt+M

  4. to sync across devices, click the popup and paste your backend config:

    {"apiBaseUrl": "https://your-backend.vercel.app", "apiKey": "your_api_key"}

android module

  1. npm run android:run — builds, installs and launches the app (needs adb; tools/android.ps1 picks a JDK 21 on its own)
  2. enable the module in your xposed framework (LSPosed / Vector) and scope it to the chat apps
  3. grant display over other apps
  4. open the GlitchDraft app and paste the same {"apiBaseUrl": "...", "apiKey": "..."} JSON
  5. tap the floating icon inside a chat to open the panel

signed release builds: npm run android:release:apk (signing comes from GD_KEYSTORE_FILE / GD_KEYSTORE_PASSWORD / GD_KEY_ALIAS env vars — the build fails loudly instead of shipping an unsigned apk).

backend

cd backend
pnpm install
# .env: DATABASE_URL=<neon postgres url>  API_KEY=<client api key>
pnpm dev
  • every client request is authenticated with the x-api-key header set to API_KEY
  • health check: GET /api/health with that header
  • deploy anywhere node runs (vercel: set the project root to backend/)

usage

  • Alt+M toggles the panel (web); on android it's the floating icon
  • type into the panel input and hit + / Alt+S to save a draft — it never touches the real composer until you say so
  • per card: use (insert into the chat), copy, edit, delete
  • the panel menu has export all, import and sync now
  • cards show when the draft was written and a Modified: line when it was changed later from another device

legacy firestore path

the extension and module can also sync through a personal firestore instead of the backend above — paste the firebase config JSON into the same popup / app screen. if you go that route, tighten the firestore rules (the permissive version below is for a throwaway test project only):

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /drafts/{document=**} {
      allow read, write: if true;
    }
    match /settings/{document=**} {
      allow read, write: if true;
    }
  }
}

Important: these rules allow anyone to read/write your data. For production, add proper authentication.

comparison

Capability GlitchDraft Form History Control II Textarea Cache Form Recover / Form Recovery Typio Form Recovery Built-in chat drafts
Chat-thread-specific saved drafts ✅ - - partial partial partial
Generic form/text-area autosave partial ✅ ✅ ✅ ✅ -
Restore/search/edit form history partial ✅ ✅ ✅ ✅ -
Messenger/Discord/WhatsApp-focused adapters ✅ - - - - partial
Image/media draft support partial - - - - partial
Cross-device/backend sync ✅ partial - - - platform-dependent
Android/WebView or LSPosed overlay path ✅ - - - - platform-dependent
Bring-your-own backend ✅ - - - - -
Local-only privacy by default partial ✅ ✅ ✅ ✅ platform-dependent
Open-source, self-modifiable stack ✅ partial ✅ partial partial -

General form-recovery extensions are stronger at broad autosave, search, cleanup, export/import, and one-click field injection. GlitchDraft is narrower but reaches a different problem: chat drafts tied to conversations, plus Android/WebView-style surfaces where normal browser form history tools do not reach.

The obvious backlog is a safer auth model, better generic form support, cleaner import/export, stronger image draft handling, and a simpler production setup story.

repo layout

path what
extension/ mv3 browser extension, plain js, no build step
android/ lsposed module (kotlin) + injected webview assets
backend/ next.js REST api + drizzle on neon
userscript/ lightweight browser injection experiment
tools/ reload-extension.ps1, android.ps1 helpers
AGENTS.md working notes: gotchas, cross-platform contracts, deploy steps

development

  • extension — edit extension/*.js raw, bump version in extension/manifest.json in the same change, then pwsh tools/reload-extension.ps1
  • every push runs .github/workflows/release-extension.yml: it packs the extension into a zip + crx and publishes a github release named after the manifest version, which is what the badge up top reports
  • android — npm run android:run (debug), npm run android:build:release, npm run android:release:apk
  • backend — pnpm dev inside backend/
  • draftSync.js, draftImport.js and styles.css exist byte-identical in both extension/ and android/app/src/main/assets/glitchdraft/ — copy your edit across. content.js is forked on purpose (native-overlay glue on the android side); its shared call contract with draftSync must change in both files.

contributors

Contributors

license

MIT

About

save and sync per-chat draft messages across devices — mv3 browser extension + lsposed android module over a next.js + neon backend. works with messenger, discord, whatsapp and instagram dms.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages