Skip to content

Releases: D4niel-dev/Orbit-beta

Orbit v0.8.7-beta

Choose a tag to compare

@github-actions github-actions released this 11 Oct 07:48

Orbit v0.8.7-beta

Version: v0.8.7-beta
Commit: b5151f2
Built: 2026-10-11

Note: A release about the composer, and about asking. The "+" finally has one door instead of five, Orbit asks for the permissions it needs once — and only for the ones that are actually missing — and four bugs that each broke something you do every day are gone: a dismissed link preview that stayed dismissed all session, a contact menu that opened empty, a contacts grid wider than the screen, and a staged attachment that vanished on the desktop.

Features

  • The Composer's "+" Is One Door Now — It used to drop a five-item list, and the first two entries were "Upload Images" and "Upload Videos" — the same intent split by file type, decided before you had seen anything. It opens a sheet now: a media panel and a pill row along the bottom, Photos · Poll · Commands · Files. The picker decides between an image and a video, so the split is gone. Camera goes straight to the camera and Gallery takes images and videos in one go. Commands is the door to the slash-command reference, which until now you could only reach by knowing to type a /.
  • Orbit Asks for Permissions Once, at Startup — Permissions were requested from three unrelated places and none of them could read the current state, so a permission you had already granted was asked for again on every single launch. One of them opened the camera on every start — getUserMedia({video:true}) and then stopping the tracks — purely to provoke the OS dialog, so the camera indicator lit up whether or not you were about to scan anything. There is one pass now, it reads what is actually granted first, and it asks only for what is missing, once per version. If everything is already granted it does nothing at all — no sheet, no dialog, no camera. The sheet says what each one is for before the system dialog appears, which is the difference between answering a question and being interrupted by one. It also asks for the two things that are not permissions and so cannot be a dialog: keeping Orbit awake in the background, and letting it open the installer for its own updates — which until now was asked for after the update had already downloaded, throwing you into Settings with the download wasted.

Improved

  • The Vault's Restore-From-File Row Moved Above the Buttons — It sat below Export and Restore, which put it after the actions it has nothing to do with and made it read as a footnote to them. It is not an action on this vault; it is the recovery path for a vault that is already gone, and the only one that survives deleting the app. Every other row on that screen is a setting, so it belongs with the rows.

Fixed

  • A Dismissed Link Preview Stayed Dismissed for the Whole Session — ⚠ Reported as "pasted links are not recognised, and links ending in / are not recognised." Neither was happening. All four combinations were measured first — typed and pasted, with and without the trailing slash — and the detection was already correct in every one. The real cause was the dismissal: it was keyed by URL for the whole session, so once the bar for a link had been dismissed, putting that same link back into the composer showed nothing at all. That is the one moment a preview is genuinely wanted, because you are looking at the link you are about to send. One cause, two symptoms, and the report pointed at neither.
  • The Three-Dots Menu on a Contact Opened an Empty Sheet — It drew the sheet and nothing but the Cancel pill. The menu only ever pushed group items and folder items, so for a direct message with the experimental folder feature off — the default — the list came out empty. A contact's actions are user actions, and there is already a sheet for exactly that, so a direct message now opens it: View Profile, Message, Mute, Close DM, Block.
  • The Contacts Grid Was Wider Than the Screen — ⚠ Reported as "it feels kinda too spaced out", which was not what was wrong. 1fr 1fr means minmax(auto, 1fr), and an auto minimum is the content's min-content width — so one long unbreakable name pushed its column wider than its share. On a 390px phone the two columns measured 188px + 229px = 426px and the right-hand cards were cut off. That is also why the ellipsis on a long name never appeared: the column had simply made room. A layout complaint is a measurement, not an opinion.
  • A Re-render Made Staged Attachments Vanish on the Desktop — ⚠ Found by a test that had been written off as flaky. renderChat rebuilds the whole composer, including the staged-attachment strip — which the template emits empty and hidden — and nothing put the staged files back into it. So any re-render while files were staged made the strip disappear while the files were still staged: they would still be sent, and you could no longer see or remove them. Not a rare path — the local-echo chat posts its greeting a few seconds after boot, so it happened on a plain cold start. The measured sequence was 3 tiles at t+0.5s, then 0 tiles with 3 still staged at t+4.5s. The spec passed about half the time, and the only difference was whether the assertion ran before or after that greeting.

Downloads

Artifact Size
Orbit-v0.8.7-beta.apk 69M
Orbit-0.8.7-beta-amd64.deb 170M
Orbit-0.8.7-beta-x86_64.AppImage 197M
Orbit-0.8.7-beta-arm64.dmg 181M
Orbit-0.8.7-beta-x64.dmg 186M
Orbit Setup 0.8.7-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.8.6-beta

Choose a tag to compare

@github-actions github-actions released this 09 Oct 16:19

Orbit v0.8.6-beta

Version: v0.8.6-beta
Commit: f2d8c7b
Built: 2026-10-09

Note: Four bugs that each broke something you do every day — an emoji you could not send, a link preview that arrived too late to be useful, a profile card that opened on top of the camera, and a backup file this app could read but never offered you. Plus the Contacts screen getting filters and a display style, and a rebuilt attachment preview.

Features

  • Restore From a Backup File — The Local Vault could restore its own directory backups and nothing else, while the desktop writes a whole account as a single .orzip/.zip. That file is now found and restored. It looks in two places — the app's own folder and vault/ — because deleting and reinstalling an app removes its data directory but not a file you saved, so a fresh install should find its own old backups rather than making you go hunting for one. It shows each file with its size, its date and which folder it is in, says how many messages it holds before you commit, and adds the account alongside what is already on the phone rather than over it. ⚠ .orzip is not a zip — the desktop writes it with gzip and a house extension — so the format is decided by the file's first two bytes, never by its name.
  • Link Previews While You Type — The preview bar appeared only after the message had gone, which is the one moment a preview is useless: you have already decided to send the link. A preview answers "what does this lead to?", and that question belongs to the moment the link is in the box. ⚠ The card inside a sent message was worse — it showed a link glyph where the thumbnail goes, the domain as the title, and then the full URL underneath, so both lines said the same thing. It now uses the page's own title and image, from the same fetch the bar uses, so the two cannot describe one link differently.
  • Filter Chips and a Display Style for Contacts — All / Online / Offline / Groups, each with a live count, and a choice between a dense list and a two-column grid of large avatars for people who recognise a face faster than they read a name. ⚠ The chip filter is deliberately momentary — it survives switching tabs and is gone after a restart, because which slice you are looking at is not a preference. The display style is the opposite: how you like to read is, so it is remembered.
  • Every Contact Row Has Its Actions — A row had one button, so everything else a person can do with a contact was reachable only by long-pressing — which is not discoverable and does not exist on a desktop. There is a second button now, opening the same sheet the long-press opens. Groups had no actions at all before this; a group was a row you could only tap.
  • The Attachment Preview, Rebuilt — Three things were wrong with the strip above the composer, and the first one was measured before anything was written: a staged image was a bare <img> in a 56px tile, so a full-resolution photo was an empty box with nothing happening in it. There is a spinner now, with the image held back until it is actually ready. Each tile carries an × that takes that one image out of the send while the rest go normally, and tapping a tile looks at it — full screen, not a send. The tiles also lift off the composer with a shadow, because a staged attachment is the one thing on screen that is not part of the app yet.
  • Only the Active Tab Is Labelled — Four labelled tabs is four words competing for a 62px bar, and three of them are always the wrong word: you are looking at one panel. The label now belongs to the tab you are on, and it moves between them.

Fixed

  • An Emoji Picked From the Picker Could Not Be Sent — ⚠ This was not the empty-check, which was fine: an emoji passes it, and typing one worked. The picker's handler assigned the input's value directly, and assigning .value fires no input event — so nothing that watches the composer ever learned the box had content. updateSendButton() never ran, the send button never appeared, and the composer sat there showing the mic. An emoji-only message was unsendable not because it was rejected but because there was no button to press.
  • Tapping "Pair a Desktop" Re-Opened the Profile Card — ⚠ A race. The account switcher closes back to wherever it was opened from, so arriving from the profile card made it re-open the card — on the same 220ms timer that opens the scanner, so the card landed on top of the camera. Tapping Pair is leaving for a destination, not dismissing the sheet, so it no longer takes the "go back where I came from" path.
  • The Restore Button's Corner Radius Was Resolving to Nothing — The whole restore block was written against --r-sm, and this app defines no such token. An undefined var() makes the declaration invalid and the browser drops it silently — five dead references, all measuring 0px. It is a real radius now, and a deliberately tighter one than the settings buttons use, because a full-width 42px button at 12px reads as a pill.
  • The Restore Confirmation Was a Desktop Dialog — A centred card floating over a bottom sheet was two surfaces doing one job. It is the sheet's second step now, and it has one way out: the sheet already pins a Cancel pill, so an in-content Cancel meant two Cancel buttons on screen — the same duplication the × removal fixed in v0.8.3.

Downloads

Artifact Size
Orbit-v0.8.6-beta.apk 69M
Orbit-0.8.6-beta-amd64.deb 170M
Orbit-0.8.6-beta-x86_64.AppImage 197M
Orbit-0.8.6-beta-arm64.dmg 184M
Orbit-0.8.6-beta-x64.dmg 189M
Orbit Setup 0.8.6-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.8.5-beta

Choose a tag to compare

@github-actions github-actions released this 07 Oct 13:21

Orbit v0.8.5-beta

Version: v0.8.5-beta
Commit: 7cf46f9
Built: 2026-10-07

Note: The phone catches up with the desktop. Orbit now appears in the Android share sheet, a notification can be answered without opening the app, and the app can be locked behind a PIN — plus link previews, a real image viewer, and a network map that shows faces instead of letters.

Features

  • Orbit Is in the Android Share Sheet — Sharing a photo used to mean opening Orbit, finding the chat, and hunting for the picture. Android's own flow — share, then pick a person — is the one your thumb already knows, and Orbit is in it now. Share a photo, a video, a PDF or a link and it asks which chat rather than guessing: sharing to the wrong person is worse than one extra tap, and "send to the last chat" is exactly the helpfulness that sends a photo to the wrong person. The text lands in the composer rather than being sent blind, so you can still say something about it.
  • Reply to a Message From the Notification — A direct message notification carries a Reply box, so you can answer without opening Orbit. This is the interaction people actually use a messenger for: you get a message, you answer it, you put the phone down. ⚠ Replies typed while Orbit is closed are queued, not sent on the spot — sending them immediately would mean running the whole P2P stack from a broadcast receiver, so they go when the app is next opened and the notification stays until then rather than pretending. DMs only: a group notification cannot say who you are replying to, and a box that cannot say where it is going is worse than no box.
  • App Lock — A PIN in front of the app, ported from the desktop's lock screen. Six digits on a keypad rather than a text field, because a PIN on a phone is digits and a thumb and a keyboard covering half the screen is the wrong instrument. The PIN is stored as a PBKDF2-SHA256 hash with a per-install salt, not as the PIN. Five wrong attempts starts a 30-second cooldown, and that cooldown lives outside settings — a cooldown you can clear by restarting the app is not a cooldown. Locks on launch always; locks on return only if you ask, because switching apps to copy something is not the same as handing the phone to someone.
  • Link Previews — The old card showed the domain, which tells you nothing you could not read off the URL. It fetches the page and reads its Open Graph tags now, so it shows what the link actually leads to: the page's own title and image, above the composer. It follows the most recent link rather than every link, because a preview answers "what is this?" and the thing you are looking at is the thing just sent.
  • The Image Viewer Grew Up — It had a close button and nothing else. It now steps through the images of the message you tapped in, with previous/next, zoom (buttons and pinch), and a download button. At the ends the buttons go dead but stay put — moving them would shift the layout under a thumb that is mid-tap. Zooming out past the picture's own size springs back after a moment, so the gesture always answers and you cannot get stuck looking at a thumbnail.
  • The Network Map Shows Faces, Not Letters — Nodes were a coloured circle with an initial. A friend with a picture shows it now. The map is a canvas, so the avatar has to be decoded before the draw loop paints, and a URL that fails is remembered as failed rather than retried every second forever.
  • Undo Send — A short window to take a message back after sending. It is a real retraction, not a local hide: it sends the same MESSAGE_DELETE the desktop already broadcasts, so the message disappears for the other side too. A "delete" that only deletes it for you is worse than none, because you believe it is gone. Off by default, in Settings → Chat — the hold menu already deletes, so this is for people who send fast and regret fast. When it is on, the affordance sits on the message itself rather than in a toast: send five messages quickly and five toasts would cover the chat you are trying to read.

Improved

  • The Update Download Is a Sheet, With States That Change — It was a centred modal built entirely from inline styles, so it could not use the app's tokens, and it had exactly one state: the title said "Downloading Orbit…" while the installer was running. It is a bottom sheet now — a download is a wait, not a question, so it should not black out the app and sit mid-screen pretending to be a decision. Downloading, Downloaded and Installing each get their own icon, title and colour, and the percentage is the thing you actually read while waiting.
  • The Local Vault's Stray Line — "A single JSON file in the app data folder (vault/)" was a separate block below the status card, which is exactly why it read as out of place: it repeated what the card already said, it had no icon where the card has one, and it was left-aligned while the card is a row. It is the card's third line now.

Fixed

  • The What's New Button Did Nothing — A docs edit had broken both hardcoded blocks behind it. Found by tapping it rather than by reading it.
  • The Image Viewer's Prev/Next Were Never Styled At All — The markup was class="viewer-nav viewer-prev" and every rule was written against .viewer-btn, so not one matched and the buttons fell back to the browser default: square, transparent, sitting in the flow side by side. CSS fails silently on a selector that matches nothing. They match the desktop's now — 50% black discs at both edges, no blur.
  • The Viewer's Backdrop Was 92% Opaque — The chat behind showed through as blocks, so a picture in the feed read as a dark rectangle beside the one you were viewing. Opaque now.

Downloads

Artifact Size
Orbit-v0.8.5-beta.apk 69M
Orbit-0.8.5-beta-amd64.deb 170M
Orbit-0.8.5-beta-x86_64.AppImage 197M
Orbit-0.8.5-beta-arm64.dmg 181M
Orbit-0.8.5-beta-x64.dmg 186M
Orbit Setup 0.8.5-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.8.4-beta

Choose a tag to compare

@github-actions github-actions released this 06 Oct 13:09

Orbit v0.8.4-beta

Version: v0.8.4-beta
Commit: c528a10
Built: 2026-10-06

Note: One tap on Send was sending a voice message. Android fires a set of synthetic mouse events after every touch, aimed at whatever is under your finger by then — and sending swapped the composer to the mic before they arrived.

Fixed

  • One Tap on Send No Longer Fires the Mic — Send fired on touchend, which swapped the composer from the send button to the mic. Android then fires a synthetic mousedown aimed at whatever is under the finger at that moment — which was now the mic — so a recording started, and the mouseup stopped and sent it. One tap, a voice note nobody asked for, and it repeated, because each one reset the composer and put the mic back under your thumb. The send icon "not lighting up" was the same stuck state: the swap had already run. Any mouse event within 700ms of a real touch is ignored now, which is longer than Android's ~300ms synthetic delay and shorter than a deliberate second tap. Both controls were also double-firing on a real tap — the mic started on touchstart and the synthetic mousedown, and send ran on touchend and mouseup.

  • A Group of Images of Different Sizes No Longer Goes Ragged — every cell took its own image’s height, so a 1:1 beside a 16:9 beside a 9:16 gave three heights in one row: the tallest set the row and the others floated inside it. The grid now follows Discord: one image keeps its own proportions, two are a pair of squares, three are one large square with two stacked beside it, four are a 2×2, and anything past four shows four tiles with a +N on the last. Tiles touch, and the grid clips so only the outer corners are rounded — which is what makes a group read as one object rather than several adjacent cards.

  • Images in a Desktop Grid Were Rendering at Half Height — the grid’s own rules were written without the .message-row .msg-attachments prefix, so they lost a specificity tie against an earlier rule that carried it. Both were !important, so the more specific one won and its height: auto and object-fit: contain applied: a wide image rendered at its natural height inside a square cell, so half the tile was empty. The grid rules carry the prefix now, and a desktop spec measures the image against its cell rather than the cell alone — a grid row stretches its cells to a common size whatever the CSS says, so a cell-only assertion passes either way.

Downloads

Artifact Size
Orbit-v0.8.4-beta.apk 69M
Orbit-0.8.4-beta-amd64.deb 170M
Orbit-0.8.4-beta-x86_64.AppImage 197M
Orbit-0.8.4-beta-arm64.dmg 181M
Orbit-0.8.4-beta-x64.dmg 186M
Orbit Setup 0.8.4-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.8.3-beta

Choose a tag to compare

@github-actions github-actions released this 05 Oct 13:13

Orbit v0.8.3-beta

Version: v0.8.3-beta
Commit: 1f7a65f
Built: 2026-10-05

Note: The conversation screen, reworked. A message is no longer one box with everything crammed inside it — text, images, files, video and audio each get the treatment their content actually wants, and your own messages stop being a different colour from everyone else's.

Features

  • The Conversation Screen, Reworked — Everything a message carried lived inside one bubble — text, images, files, video, audio — so a photo had a bubble around it (a frame around a frame) and a file was whatever was left over. Attachments now sit beside the bubble, and each kind gets what it actually wants: text keeps its bubble, images get none at all and keep their natural aspect instead of being forced into a square and cropped, files get a surface of their own, and video and audio float on the feed behind a shadow. Your own messages are no longer a solid block of accent — same surface as everyone else's, with the corner radius saying which side you are on. A Classic Bubbles toggle in Chat settings brings the accent back.
  • The Desktop Got the Same Conversation Rework — The phone had it and the desktop did not, so the two laid messages out differently: the desktop still wrapped every photo in a bubble and drew a generic glyph for every file. Ported: attachments beside the bubble, images with no box and their natural aspect, files on their own surface, video and audio behind a shadow, and reactions straddling the bubble's bottom edge. Deliberately identical in behaviour to the mobile so the two cannot drift apart.
  • Every File Draws Its Own Icon — A .zip, a .json and a .pdf were a column of identical generic glyphs. The mapper moved to shared/ui/file-icons.js, which both platforms read, and it knows archives, code, spreadsheets, slides, audio, video, PDFs and plain text.
  • The Bubble Colours Were Hardcoded — #1A1D24 for incoming and a fixed blue gradient for outgoing, neither of which followed the theme. In a light theme the incoming bubble stayed dark while color: var(--text-primary) went dark with the rest of the app — so the message text vanished into its own bubble. That was Dan's "fix this" screenshot, and it was invisible in the dark theme, which is why it survived. Tokens now, and the text is 17.3:1 on its bubble in dark and 17.8:1 in light.
  • The × Is Gone From the Attachment Pills — Staged files carried a close button on every pill, and the composer already has a Cancel that clears them. Two controls for one job, and the × was the smaller, harder one to hit on a phone. Removed on both platforms.
  • The × Is Gone From the Bottom Sheets Too — Same duplication, one level up: every sheet had a × in its top-right and a Cancel pill across the bottom. The × is removed. Backdrop tap and drag-down still dismiss, so nothing is trapped. Two sheets keep theirs — the frame picker and What's New have no other way out.
  • The Local Vault Fits the Rest of the App Now — Its status was a centred block with centred sub-text, in a settings list where every other row is left-aligned, which is what made it read as bolted on. It is a card now, like the rows around it. And its two actions were both primary, which made the eye choose between things that are not equal: exporting is routine, restoring replaces everything you have. Export keeps the accent; Restore steps back. While in there: a stored backup time that could not be parsed rendered the literal words "Invalid Date" into the UI — it falls back to "No backup yet" now.

Downloads

Artifact Size
Orbit-v0.8.3-beta.apk 69M
Orbit-0.8.3-beta-amd64.deb 170M
Orbit-0.8.3-beta-x86_64.AppImage 197M
Orbit-0.8.3-beta-arm64.dmg 181M
Orbit-0.8.3-beta-x64.dmg 186M
Orbit Setup 0.8.3-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.8.2-beta

Choose a tag to compare

@github-actions github-actions released this 04 Oct 12:19

Orbit v0.8.2-beta

Version: v0.8.2-beta
Commit: a828468
Built: 2026-10-04

Note: A maintenance release. Nothing new to look at on purpose — this is the mobile restyle's own regressions, closed out. The redesign shipped in v0.8.1 and then a run of things it had quietly broken surfaced: a contacts list that flipped between two renderers, a tab strip that was hidden unless you had already created a folder, and custom profile banners that had stopped rendering without anything looking wrong. Diagnostics was rebuilt while I was in there. If you were on v0.8.1 and something felt off, it was probably one of these.

Features

  • The Phone Offers All 55 Profile Frames — The desktop enumerated 1–55 and the phone's picker stopped at 42, so twelve frames were simply not there. Nothing errored and nothing looked wrong: a picker missing its last entries is indistinguishable from a picker that ends there. Both platforms now read one list, shared/ui/profile-frames.js, and a test fails if the list and the shipped PNGs ever disagree — in either direction, so a frame file nobody can choose is caught too.

  • Diagnostics, Rebuilt — It was a section title repeating the screen header, one card, six bare rows floating on the background with nothing under them, and the top third of a screen filled. It opens with a verdict now — "Everything checks out" or "Something needs a look", with a count of how many checks passed — the checks sit in one grouped card instead of loose on the background, and the report is shown in a monospace block rather than only described. "Copy these values to paste into a bug report" was a promise about content you could not see; the same promise kept is the actual text. The Copy button and the preview come from one builder, because they were two separate loops over the same rows and would have drifted the first time either changed.

Bug Fixes

  • The Contacts List Kept Changing Its Mind — Two renderers wrote to the same #friends-list: a grouped one (Online / Offline / Groups, with a Message button) and an older flat one (a chevron, and a cat at the end). Whichever ran last won, and the flat one is called from a dozen places — a friend added, a presence change, a profile saved, a search — so the list flipped to flat on almost any update. Dan saw it as "correct, then incorrect" and the trigger he hit was the search box. There is one renderer now, and the test drives that exact path.
  • The Friends / Groups Tabs Were Hidden Unless You Already Had a Folder — The markup was there and the folder machinery was there. One rule — #home-tabs:not(.has-folders) { display: none !important } — meant the strip only appeared to someone who had already created a folder, so the folder feature was gated behind itself and the Friends/Groups control was unreachable for everyone else. It came from the restyle, on the reasoning that groups already render inline in the list. That reasoning cost the only way to scope the list to one kind. The strip is back, and it now sits above the "Active now" row rather than below it — it scopes everything under it, and "Active now" is a list of online friends, so it has no business sitting above the Groups tab.
  • Tab Transitions Only Went One Way — The direction came from the caller, and the only caller passed tabId === 'chats' ? 'reverse' : 'enter' — so the direction was really "is the destination Chats?", and every move that did not involve Chats went the same way. Going Chats → Contacts → Activity → Contacts, the last step slid left when it should have slid right. It is derived from the panel order now, so it always slides the way you are moving.
  • The Content Slide Had No Direction, and the Panel's Fade Came Back With It — The transition animates each panel's content, not the panel, because the tab bar lives inside every panel and animating the panel drags the bar with it — the bar had been measured still at 276 samples across a switch. But the content keyframes were not directional: entering always came from +16px, so "back" looked identical to "forward" even once the direction was correct. And removing the rule that keeps the panel animation off brought the panel's own keyframes back into play, fade included — panelEnter/panelExit carry opacity, which is why the slide started dissolving instead of sliding. The content now has a Reverse pair, the panel animation stays off, and there is no opacity anywhere in the transition. All three are pinned by a test that asserts the animation that actually lands, the panel staying still, and the bar holding one position.
  • The Profile Avatar Sat Inside the Banner Instead of Across It — With the hero's own 44px padding an 88px avatar ended at 132px, entirely within a 150px band — so nothing crossed the edge and the whole header read as crammed against the top with dead space beneath it. The band is 108px now and the avatar starts at 64px, so 44px of it sits below the edge.
  • Cropping a Banner Did Nothing to the Hero — Three separate places painted the banner with heroEl.style.backgroundImage = 'url(...)', and .profile-hero { background: transparent !important } resets background-image — a stylesheet !important beats a non-important inline style, so all three were no-ops. You cropped a banner, the modal closed, the URL field filled in, and the hero did not move. The save path also gated the banner on avatar, so saving with no avatar set cleared the banner you had just chosen. All three go through one setHeroBanner() that writes the <img> layer now.
  • The Gap Under the Profile Name Was a Hole — Between the tag and "Edit Profile" there was about 79px of nothing: 30px of hero bottom padding, 6px of hero margin, 16px on the form's wrapper and 10px on the section, all stacking. The wrapper was a bare <div style="padding: 16px"> with no class, so nothing could target it. It is 18px now, and the header sits about 45px higher.
  • The Avatar Had No Ring Over a Photo — The restyle sets border: none !important on the avatar, which is right on a plain card and wrong over a banner: it merged into the image and read as a square rather than a circle. The 3px surface ring is restored only when there is a banner to separate it from.
  • Custom Profile Banners Were Invisible on Mobile — The banner was applied as an inline background-image on .profile-hero, and the restyle sets background: transparent !important on that element. The shorthand resets background-image, and a stylesheet !important beats a non-important inline style — so every custom banner silently stopped rendering, and it read as deliberate because the blurred accent was still sitting there behind it. All three profile heroes had it (your profile tab, your profile sheet, and a friend's). The banner is an <img> layer now, which no background rule can reach. The desktop was never affected — it puts the banner on a dedicated #profile-banner element with no CSS rule on it.

Technical

  • The Restyle Layer Has Three Shapes That Keep Catching Things — Every bug it has caused is one of them: a bare img or * child selector (it caught the profile-frame overlay), a :not(...) on a state class (it hid the tab strip unless you already had a folder), and a background shorthand with !important (it reset an inline background-image, so custom banners were invisible). All three read as deliberate once they land, which is why none of them were noticed. When writing in that file, prefer the narrowest selector that does the job and never set position when all you need is z-index — a blanket child selector that sets position takes it away from the children that are deliberately absolute, which is how the profile sheet's two buttons ended up stacked down the left edge.
  • Test Suites — npm run test:unit is now 11 suites; npm run test:mobile is now 134 checks across eleven probes; the desktop Playwright suite remains 37 tests across two shards. The new probes cover the Contacts list, the home tabs and Diagnostics.

Downloads

Artifact Size
Orbit-v0.8.2-beta.apk 69M
Orbit-0.8.2-beta-amd64.deb 170M
Orbit-0.8.2-beta-x86_64.AppImage 197M
Orbit-0.8.2-beta-arm64.dmg 181M
Orbit-0.8.2-beta-x64.dmg 186M
Orbit Setup 0.8.2-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repositor...

Read more

Orbit v0.8.1-beta

Choose a tag to compare

@github-actions github-actions released this 03 Oct 09:59

Orbit v0.8.1-beta

Version: v0.8.1-beta
Commit: 67d6275
Built: 2026-10-03

Note: The phone release. Your account can now travel from the desktop to a phone over your own network, encrypted, and land as a second account rather than overwriting the one already there. Around it, the mobile UI redesign that had been landing piece by piece is finished — the conversation screen, the composer, the gallery, the profile card and search all now belong to the same app. And the search itself was not working: message search could only ever find messages in the conversation you already had open.

Features

  • Your Account, From the Desktop to Your Phone — The desktop has been able to back itself up for a while, and the phone has never been able to receive any of it. Now it can: open Link a phone on the desktop, scan the code with Settings → Pair a desktop, and the account comes across your own network. It arrives as a new account on the phone — your existing one is untouched, and you choose when to switch — because the alternative, quietly overwriting the account already in your hand, is the one outcome nobody could undo.

    What authorises the transfer is the link token: 128 random bits, minted when you ask to link a phone, shown only as a code on the desktop's own screen and never sent in the clear. The phone proves it holds the token by deriving the same encryption key from it. The desktop does not build or send anything until you confirm, and the confirmation says what is about to leave and how much of it — account, message count, contacts, size. The token is burned the moment a transfer starts, succeed or fail, and a refusal burns it too: a replay of the same request cannot pull a second copy.

    Everything travels under PBKDF2-SHA256 (100,000 rounds) → AES-GCM-256, the same scheme as the Local Vault, so a tampered bundle fails to decrypt rather than importing garbage.

  • The Mobile UI, Finished — The redesign had been arriving in pieces since v0.8.0. This release is the rest of it, and the parts that were still wearing the old language now match:

    • The tab bar shows the filled form of the selected tab's icon. Two of the four icons had to change to make that possible — filling an outline only says something if the glyph has internal shape, and activity (a polyline) filled into a lump while history filled into a ball at 24px. Activity is a bell now, which is also what that panel is.
    • The conversation screen — day separators, so a thread with only times in it is not a puzzle; outgoing bubbles are a shallow gradient rather than the accent at full strength, which across a long conversation is a wall of saturated blue; incoming bubbles get a hairline so they read as a surface.
    • The composer had four controls in a 48px pill. The emoji picker now lives inside the field, where composing happens, and the trailing button swaps between mic and send — mic when there is nothing to send, send when there is.
    • The Gallery gets a header that names the conversation and counts what is in it, filters on the shared pill scale, a 3-up/2-up layout toggle, and empty states that distinguish "none of that kind" from "nothing at all".
    • The profile card opens from the header avatar, and the account switcher moved one tap in behind a button on its top-left. The hero had been carrying a magenta gradient from the previous palette — the last off-accent colour on a live path in the app.
    • Settings sections are full-bleed again. Wrapping a dozen rows in one card made the whole section read as a single enclosed block, and the side margins were eating width the rows had no use for.
  • Search That Actually Searches — Message search found nothing outside the open chat. It read the store's message map directly, but that map is lazy-loaded — only the conversation you are looking at is in memory — so every other chat resolved to an empty array. Searching a word that appears in three conversations returned zero results. It returns three now, and the index is built through the store's own loader, cached for the duration of a search rather than rebuilt on every keystroke.

    With that working, search grew filters: All / Chats / People / Messages on the global search, each with a count of what the query found — a pill stays visible at 0, so "no messages match" is something you can see rather than a category that silently is not there. People are matched by tag as well as name, because #7714 is the half of a handle you would actually search for. Searching inside a conversation gets its own filters — All / Media / Links / Voice — which work with an empty query too, so tapping Media browses that chat's media rather than matching nothing.

  • A Test Suite for the Mobile — The mobile had none, and every regression that actually shipped was found by driving the real UI in a browser. Those checks used to be throwaway scripts that got deleted each time; they live in mobile/tests/ now, 71 checks across seven probes, run with npm run test:mobile. They use the Edge already on the machine, so there is no browser download.

Bug Fixes

  • The Mobile's What's New Had Stopped Three Releases Ago — The list on the phone is hand-maintained and had not been touched since 0.7.5-beta, so anyone who updated opened Settings → About → What's New and found nothing newer than 0.7.5. Nothing errored; there was simply no check that the newest entry is the version being shipped. 0.7.6, 0.8.0 and 0.8.1 are in it now, and npm run test:mobile fails if the newest block is not the version in package.json — on both platforms, because they are two separate hand-maintained files with two different function names (vBlock on mobile, versionBlock on desktop), and a grep for one finds nothing in the other.
  • Profile Frames Had a Solid Square Behind Them — Two !important rules of equal specificity: components.css sets the frame's background transparent, and the restyle layer sets background on .profile-avatar-wrapper img, which also matches the frame. Equal weight means !important does not break the tie — load order does, and the restyle layer loads last. The frame rule is now heavier than any img rule that could catch it, so it cannot be beaten on order again.
  • The Settings Search Never Hid Anything — Typing in it marked nine of ten rows as hidden and left every one of them on screen, because the restyle layer pinned display: flex !important on the row and that beats a .hidden rule. The feature had been broken since the restyle shipped, and it hid well: a search that does nothing looks exactly like a search with no results.
  • Two More Show/Hide Breaks, Same Cause — The composer's mic/send swap and hiding the "Active now" row during a search both failed for the identical reason. All three were the same mistake in the same file: an !important on a property something else needs to toggle.
  • The Activity Title Sat 20px Left of Centre — It used position:absolute; left:50%; translateX(-50%), the textbook centring idiom, which does not work here: an absolutely positioned block with no width shrink-wraps to the available space, not to its text, so it measured 326px wide and the translate moved it by half of that.
  • The Navbar Moved When You Changed Tabs — The tab bar is injected into every panel, so animating the panel slid the bar with it. The bar is the one thing that should look like it never moved; the panels are sequential, so animating their contents instead keeps it perfectly still. Verified by sampling the bar's position every 16ms across a switch: 276 samples, one position.
  • Switching Accounts Could Take the Wrong Data With It — Two of the three were pre-existing: settings that belong to one account were being read by the next, and a profile frame could follow you across a switch.
  • save() Does Not Persist Messages, and the Importer Assumed It Did — Messages are written one chat at a time; there is no set('messages') in save(). The account importer put the whole history in memory where it looked completely correct and would have been gone on the next boot. Caught by asserting after the reload rather than before.
  • The Last Row of Every Settings Section Was Clipped — A flex item shrinks by default and the card set overflow: hidden, so the final row was cut off with no way to scroll to it.
  • The Settings Toggle Knob Was Off-Centre and overhung its track; a group label lined up with nothing; and section titles sat 4px off their own icon — the same 4px, three separate places.
  • A Video With No Poster Was a Nearly Invisible Square, and an audio attachment sat in a single grid cell as a square tile with a filename crammed inside it.
  • The Images Tab Was Showing Video and Audio — And their thumbnails cannot load, so both appeared as broken images.

Technical

  • The Transfer's Threat Model Is the Design — The desktop listens on the LAN, so anything on that network can open a socket to it. The entropy of the link token is what the security rests on, not the KDF — do not shrink it because "there are 100,000 iterations". The receive side never trusts the sender: every field is bounded and typed, the iteration count is clamped into a sane range so a peer cannot talk you into a one-round KDF, and the assembled length is checked against what the offer promised so a truncated transfer cannot look complete.
  • desktop/src/js/network/protocol.js Is Hand-Maintained, Not Generated — A packet type added only to shared/ does not exist on the desktop, and a receive branch for it can never match. This is what made SETTINGS_SYNC look unwired for two releases. All five transfer types went into both copies. (mobile/src/shared/ is generated — npm run shared:sync.)
  • **An !important on a P...
Read more

Orbit v0.8.0-beta (Stable)

Choose a tag to compare

@github-actions github-actions released this 01 Oct 05:53

Orbit v0.8.0-beta — Stable Release

Version: v0.8.0-beta
Commit: 3d1e34f
Built: 2026-10-01

Features

  • Your Theme Now Follows You to Your Phone — The pieces for this had been sitting in the codebase since v0.7.3: a whitelist of what may travel, validation on receive, last-write-wins by timestamp. What was missing was the wire. Changing your theme on the desktop now sends it to your own devices — a peer with your userId is you on another machine, and a peer without it is someone else — and the phone applies it. A custom theme's colours travel too, which is the half that matters: the colours are the theme, and until now the name went and the colours stayed behind.
  • Search That Uses the Database — Message search was pulling every message into JavaScript and running includes over it. It now goes through SQLite's FTS5, so project AND deadline is answered by the engine in milliseconds regardless of how much history you have. Prefix matching (deadl*) works, results are ranked by relevance rather than recency, and search can be scoped to one chat. The old scan remains as a fallback for builds without FTS5.
  • A Search Icon in the Shared Media Bar — Inside the field, where it belongs.

Bug Fixes

  • The Update Progress Bar Never Moved — It sat at 0% for the whole download while the label counted megabytes. The total came only from Content-Length, and the mobile's Response is patched to buffer the whole body, so that header is often absent — which left the bar with nothing to divide by. The release asset's declared size was already being read further down to verify the download; it works just as well as the denominator.
  • A Custom Theme's Colours Never Reached the Phone — The module has always whitelisted them and the mobile has always applied them. The colour editor writes to the store directly rather than through the settings funnel, so the broadcast never fired for it. Theme changes went through the funnel and synced; colour changes did not. The apply handler also skips a re-render for the same reason, now fixed with it.
  • The Images Tab Was Showing Video and Audio — And their thumbnails cannot load: a video has no still to show and an audio file has none at all, so both appeared as broken images. Images means images; video and audio go to Files where they get a proper type icon, and the Type filter only offers kinds the current tab can contain.
  • Changing the Display Refreshed the Whole Window — The grid/list toggle wrote its preference through store.setState, which notifies every subscriber — the chat panel, both sidebars, the gallery. Flipping the view now causes zero chat renders.
  • Two Galleries at Once — The Shared Media panel is an overlay anchored to the chat and the gallery takes the full width. Opening the gallery closes the panel.
  • No Way Out of Select Mode — The bulk bar only appeared once something was picked, so entering the mode with nothing selected showed no bar and no way back. It is visible whenever the mode is on, with the action button disabled until something is chosen.
  • Long Filenames Spilled Out of Their Cards — A grid item refuses to shrink below its content without min-width:0, so a long name pushed the card over its neighbour. The ellipsis was already on the name; it had nothing to work with.
  • The Send Button Could Strand You — The composer is rebuilt when a chat re-renders, and anything typed into the old input goes with it. With the button carrying disabled, a rebuild left a visible composer with an inert button and nothing to explain why. It still shows when it can send — the fill and the accent colour — but it no longer carries an attribute that can leave you with no way forward.
  • A Toast Could Swallow the Send Button — The toast stack sits at the bottom-right, which is exactly where the send button is, and its close button takes pointer events. A toast arriving as you went to send ate the click. The stack now clears the composer. This one predates the composer work; the button used to sit differently, which is why nobody had hit it.

Technical

  • Two protocol.js Files, and the One That Matters — The desktop has its own copy and loads that one, not shared/. It never received SETTINGS_SYNC — the shared twin has had it since v0.7.3 — so the packet type did not exist on that platform and the receive branch could never match. Found by probing the constant: it was undefined. When adding a packet type, check both files.
  • FTS5 Is a Compile-Time Option — The migration that builds the index catches the failure and returns rather than letting the app fail to boot, and searchMessages returns [] instead of throwing — including for a malformed query, which throws inside SQLite. A missing search index must never stop the app starting.
  • FTS5's Operators Are Uppercase — The query is lowercased for the scoring, so project and cancelled reached SQLite with a lowercase and, which FTS5 reads as a search term rather than an operator. The engine's syntax and the app's normalisation are two different concerns; they are handled separately now.
  • var Is Function-Scoped, Which Bit Me — A local named hits inside the search function shadowed the results array of the same name, so raw database rows were pushed into the results and the render read .msg off a row that has no such property.
  • Cache Stamps Moved — For app.js, store.js and version.js. store.js had not been stamped since August.

Downloads

Artifact Size
Orbit-v0.8.0-beta.apk 68M
Orbit-0.8.0-beta-amd64.deb 170M
Orbit-0.8.0-beta-x86_64.AppImage 196M
Orbit-0.8.0-beta-arm64.dmg 180M
Orbit-0.8.0-beta-x64.dmg 186M
Orbit Setup 0.8.0-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.7.6-beta

Choose a tag to compare

@github-actions github-actions released this 30 Sep 16:59

Orbit v0.7.6-beta

Version: v0.7.6-beta
Commit: 5ea5f3c
Built: 2026-09-30

Features

  • The Shared Media Panel Grew Up — It was a list of pictures and files with no way to find anything in it. It now has a search box, a filter by sender, kind and age, a grid/list toggle, a jump to message on every item, multi-select with download-all, and it renders sixty items at a time with a "Showing 60 of 412" count instead of building the whole list on every keystroke. The filter is three rows of chips in its own popover rather than a menu, because a flat action list cannot express "pick one sender, one kind, one age"; clicking the active chip clears that row, and the button carries a dot while anything is filtered so a filtered panel is never mistaken for an empty one.
  • Storage Stats, Because Orbit Keeps Your Files — Orbit is local-first: every attachment is on your disk, and until now there was no way to see how much there was or where it went. The gallery header reads "3 items · 4.9 MB" and clicking it opens a per-chat breakdown, biggest first, with a bar each. A total does not answer the question a local-first app raises — the ranking does.
  • Select and Delete Media — With the stats in place, the obvious next question is "so let me reclaim some". Select mode in the gallery picks items and deletes them, and the confirm says plainly that the message goes for both people, because "delete" in a gallery could reasonably mean three different things and the wrong guess destroys history.
  • A Month Scrubber — The gallery is a flat list, so finding that photo from March meant scrolling and hoping. A rail down the right lists the months that actually have media and jumps to the first item of each.
  • The Composer Says What It Can Do — The attach button is a plain plus that rotates into an × while its menu is open (a + turned 45° is an ×, so the open state needs no second icon). The send button is dimmed and inert with an empty box and lit with a filled arrow when there is something to send — including when the only thing staged is a file, because an image with no caption is a perfectly good message. It used to be always pressable with a handler that silently did nothing, which is worse than a button that tells you.
  • A Reason to Hover a Button You Cannot Press — Hovering a disabled send shows a random icon from the 1,958 in lucide. Only while it is disabled: when it can be pressed, the filled arrow is the thing that says so, and hiding that behind a joke would make it a worse button.
  • The Slides Have Some Pop — The first-run carousel and the tutorial card now rise in, then animate their parts on a 60ms stagger with a slight overshoot. Everything arriving at once reads as a swap; the same content arriving in sequence reads as something happening.

Bug Fixes

  • The Images Tab Was Not Showing Images — Video and audio counted as "media" and landed in the Images tab, where their thumbnails cannot load: a video has no still to show and an audio file has none at all. Both rendered as broken images. Images now means images, video and audio go to Files where they get a proper type icon, and the Type filter only offers kinds the current tab can contain.
  • Changing the Display Refreshed the Whole Window — The grid/list toggle wrote its preference through store.setState, which notifies every subscriber — the chat panel, both sidebars, the gallery — so flipping the view re-rendered the entire app. The setting only needs persisting; it no longer touches the store. Flipping it now causes zero chat renders.
  • Two Galleries at Once — The Shared Media panel is an overlay anchored to the chat and the gallery takes the full width, so opening the gallery with the panel open showed both. The gallery now closes it.
  • No Way Out of Select Mode — The bulk bar only appeared once something was picked, so entering select mode with nothing selected showed no bar and no way back. It is now visible whenever the mode is on and its action button is disabled until something is chosen.
  • The Filter Emptied the Panel Instead of Saying So — The search filter ran after the empty-state check, so it emptied the list and the render carried on with nothing, leaving a blank panel rather than "Nothing here matches".
  • "NaN" Was Not a Date — The panel's day groups were labelled NaN. new Date("1785589248803.0") is an Invalid Date — the timestamps come back from storage as strings with a trailing .0 — and this is the third place that bug has appeared, so it now uses one shared parse.
  • Long Filenames Spilled Out of Their Cards — A grid item defaults to min-width:auto and refuses to shrink below its content, so a long name pushed the card wider than its column. The ellipsis was already on the name; it just had nothing to work with.
  • The Filled Emoji Was a Blue Disc — Filling lucide's smile fills its outer circle, so the icon became a solid blob with no face in it. The lit state is the accent colour alone now.

Technical

  • setState Is for State the App Reacts To — The display-toggle bug above is the general shape: a preference that only one view reads does not belong in the store, because every subscriber pays for it. It belongs in Storage.set.
  • The Scroll Had to Go Through the Render — Jumping to a message scrolled the feed by hand, and the scroll was undone every time, because closing a side panel sets off a re-render and that render scrolls to the bottom. It now sets _pendingActivityScrollMsgId and asks for a render, so the scroll happens inside the render where it survives. The mechanism already existed — it is how the activity centre jumps.
  • Icons Built Synchronously — The send and emoji icons are built with lucide.createElement rather than a createIcons pass. That pass is timing-sensitive in this app — the transfer strip keeps inline SVG for exactly this reason — and createElement has no timing to lose.
  • The Cache Stamps — Moved for every file this release touches, per the note in v0.7.5 about a released fix sitting behind a stale file.

Downloads

Artifact Size
Orbit-v0.7.6-beta.apk 68M
Orbit-0.7.6-beta-amd64.deb 170M
Orbit-0.7.6-beta-x86_64.AppImage 196M
Orbit-0.7.6-beta-arm64.dmg 180M
Orbit-0.7.6-beta-x64.dmg 186M
Orbit Setup 0.7.6-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!

Orbit v0.7.5-beta

Choose a tag to compare

@github-actions github-actions released this 29 Sep 11:38

Orbit v0.7.5-beta

Version: v0.7.5-beta
Commit: 652fd59
Built: 2026-09-29

Features

  • 55 Profile Frames — Up from 43. The picker had stopped one short of the art it already had, so the last frame could not be reached at all, and it drew its options from a range rather than from the files: a missing asset would have shown as a broken tile. It now lists the numbers that actually exist, and every tile was checked against the frame it shows rather than the count being trusted.
  • Jump to Latest, and a Word When You Are Reading Old Messages — Mobile had no way back to the bottom of a conversation, which the desktop has had all along. A chip now floats over the foot of the messages when you are scrolled up, and it is worded by what you are actually looking at: "Jump to latest" over recent messages, "Reading old messages" past a week, and "Messages from months ago" past two. Being 400 messages behind is a scroll; reading last month while the conversation moved on is a user who does not know they are lost, and those are not the same problem.
  • Nineteen Slash Commands You Could Only Find by Guessing — The only door to the command reference was knowing to type a /. There is now a Commands entry in the + menu.
  • Copy Your User ID — On both platforms. It is a monospace string whose entire purpose is to be handed to someone else, and there was no way to get it out of the app. The desktop's profile has a copy button beside it; the mobile's profile pill has one beside the gear.
  • Swipe the Pinned Bar — With several pins the bar showed only the first, and "Show all" was the only way to reach the rest — fine for reordering, wrong for glancing. Swiping moves through them, with a dot per pin, and the tap jumps to the pin being shown.
  • A Quieter Chat Header — The members button is folded into the ⋮ menu beside it, which already offers Group Info. Four icons on a 390px header was one too many, and that was the least-used.
  • The Search ✕ Behaves Like One — It used to clear the query and close the search in a single tap. Now it clears when there is text and closes when there is not.
  • Show Group Created Date — A setting, on by default, for whether a group's info says when it was created. A group with no recorded date no longer prints "Created Unknown"; the row is simply absent, which is what it should always have done.

Bug Fixes

  • /help Opened and Closed Inside One Tap on Mobile — Pressing send on /help in a group cleared the input and then showed nothing at all, and the command came back if you left the chat and returned. Both halves were the same bug: the send button binds touchstart to dodge the 300ms click delay, so the sheet opened during the gesture — and the same gesture's click then landed on the backdrop, whose handler is hide(). It opened and closed inside a single tap. The input was cleared because the sheet genuinely had opened; the text came back because nothing had been sent and the draft was still there. The shared sheet now ignores a backdrop tap within 400ms of becoming active, which is the same shape as the _touchTap guard the input area already carries, and it fixes every sheet rather than just this one.
  • A Sheet That Opened Off-Screen Reported Success — The caller decided whether the command list had opened by reading the overlay's class, and the class said active while the sheet sat parked below the bottom of the screen. It now checks the class for the immediate decision — the sheet is mid-animation at that instant — and confirms 700ms later that it is actually on screen, saying so if it is not. A silent failure that eats what you typed is the worst possible outcome, and this one had already survived a round of instrumentation.

Technical

  • The Cache Stamps, and a Fix That Might Not Have Reached Anyone — Chasing the /help bug turned up something worse than the bug: bottom-sheet.js had changed for that fix and its cache stamp was never moved, so a device holding a cached copy would still have had the fault. That is exactly the version-skew case AGENTS.md warns about, and it means a released fix can be sitting behind a stale file. Stamps are now moved for every file that changed, and the helper that does it takes the stamp as an argument so a run is reproducible.

Downloads

Artifact Size
Orbit-v0.7.5-beta.apk 68M
Orbit-0.7.5-beta-amd64.deb 170M
Orbit-0.7.5-beta-x86_64.AppImage 196M
Orbit-0.7.5-beta-arm64.dmg 180M
Orbit-0.7.5-beta-x64.dmg 186M
Orbit Setup 0.7.5-beta.exe 163M

Installation Notes

Desktop builds are currently unsigned.

  • Windows: Microsoft SmartScreen may appear. Select More info → Run anyway if you trust the source.
  • macOS: You may need to right-click the application and choose Open on first launch.
  • Android: Because Orbit is distributed outside the Google Play Store, Android or Google Play Protect may display a warning before installation. Continue only if you trust the release source.

Verify Your Download

A SHA256SUMS.txt file is included with this release.
Since v0.3.0-beta, the checksum file is also GPG-signed (SHA256SUMS.txt.sig).

Use the Orbit Release public key to verify:

# 1. Import the public key
curl -O https://raw.githubusercontent.com/D4niel-dev/Orbit-beta/main/security/public-key.asc
gpg --import public-key.asc

# 2. Verify the signature
gpg --verify SHA256SUMS.txt.sig SHA256SUMS.txt

# 3. Verify your downloaded file
sha256sum --check SHA256SUMS.txt --ignore-missing

For Windows PowerShell:

Get-FileHash Orbit-Setup.exe -Algorithm SHA256
Compare-Object (Get-Content SHA256SUMS.txt) (Get-FileHash Orbit-Setup.exe -Algorithm SHA256) -Property Hash

Security

Orbit is designed for trusted private networks and local-first communication.
Official releases are published exclusively through this GitHub repository.

Links

  • Repository Orbit-beta
  • View the changelog for the latest changes!
  • Having issues with the app ? Click here to report it!