Linkora: a link organiser that stores pages on your own device
Local-first multiplatform link organizer with optional self-hosted sync.
At a glance
- What is it?
- Linkora is a Kotlin Multiplatform bookmark manager for Android, desktop and web that keeps folders, tags, notes and saved pages in a local Room database, and syncs only when you run your own server. The saving feature is the unusual part: web pages are stored as standalone HTML files processed entirely on device.
- Who is it for?
- Linkora suits people who want one bookmark library across Android, desktop and web without handing their reading list to a hosted service, and who are willing to run a sync server if they want their devices to converge. It does not suit anyone who expects turnkey multi-device sync, since the sync server is a separate repository you have to deploy and configure yourself, and it does not suit a workflow that needs shared links with colleagues.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A bookmark manager that treats the page as a file you own
Linkora is described as a local-first multiplatform link organiser with optional self-hosted sync. It saves, organises and syncs links between Android, desktop and web, and the README is clear that three activities sit side by side: quick bookmarking, saving webpages locally as standalone HTML files, and managing a structured folder hierarchy with tags.
That third feature is the ordinary bookmark manager part, and it is thorough. Unlimited folders and subfolders with tag support, copying and moving links and folders between them, multiple view layouts in Grid, List and Staggered form, AMOLED theme support, highlighting important links, archiving old ones, customisable link metadata with automatic recognition of images and titles from web pages, panels for quick access to folders, sharing into it from other apps on Android, and sorting, searching, import and export in JSON and HTML formats with auto-backups.
The distinguishing feature is the second one. Saving a webpage as a standalone HTML file with all processing happening completely on your device means the archive survives the link rotting. A bookmark is a promise about a URL that may 404; a saved page is a file. The trade is disk space and the fact that you must open the local copy rather than the live site.
The target user is therefore someone building a personal archive rather than a quick-save list, and the data is theirs because nothing is uploaded unless you run a server.
One shared Kotlin module behind three application targets
The repository layout is the story of the architecture. The top level entries include androidApp/, desktopApp/, webApp/, shared/, web-capture/, locales/, gradle/, fastlane/, kotlin-js-store/ and docs/, alongside the usual build.gradle.kts, settings.gradle.kts and gradle.properties.
The shared/ module is where the logic lives, and the platform directories are thin shells around it. That is the standard Kotlin Multiplatform arrangement, and the build list names the technology stack precisely: Kotlin Multiplatform with Compose Multiplatform and Material 3 for the interface, SQLite with Room for local storage, Ktor for networking, coroutines and Flows for async work, Ksoup for HTML parsing and metadata extraction, Coil for image loading, and the kapture library for saving webpages as standalone HTML files.
Two details in that list matter for behaviour. The custom cursor-based reactive and resource-aware paginator is how long lists are read out of SQLite without loading everything, which is the difference between a bookmark list that stays smooth at tens of thousands of entries and one that stalls. And the mention of custom syncing mechanisms for handling syncing with a remote server tells you the sync protocol is not off-the-shelf.
On Android specifically, WorkManager handles snapshots, web-page captures and bulk metadata refresh of links, so the expensive work of fetching and parsing pages happens in the background rather than on the main thread. The complete dependency list lives in gradle/libs.versions.toml, which is where you would look before upgrading anything.
Sync is a separate server you may never run
The sync story is deliberately opt-in, and it lives outside this repository. The README points to three sibling repositories: sync-server, browser-extension and proxy. The feature list says you can keep your data in sync across devices with an optional self-hostable sync-server, and the documentation links point to a technical write-up on how sync works and to server setup instructions in docs/ServerConnectionSetup.md.
The optionality is the point. If you use Linkora on one device, there is no server to run and no account to create, and your data stays local. If you use it on several, you deploy the sync server yourself and point your clients at it.
The browser extension extends that arrangement. It saves web links directly to Linkora via the sync-server, which means the extension is a thin client that needs your server reachable. That is also the security boundary to think about: your link archive, including any private or saved pages, is reachable by anything that can talk to the server you deployed.
One warning in the README deserves attention for anyone evaluating the project: the linkora-app.netlify.app site is stated to be the only site maintained by the author, and anything else is unrelated. Read that as a caution about lookalike sites rather than as an invitation to use that deployment, since the emphasis of the project is on self-hosting your own server.
Getting it onto Android, desktop and Arch Linux
There is no build command to publish here, because Linkora is distributed as finished applications rather than as a library. The README points to a GitHub releases page, to F-Droid with the package id com.sakethh.linkora, to Google Play, and to an Arch User Repository package named linkora-bin. Desktop and web builds come from the same release stream.
The top level directory listing shows what a source checkout is made of, which matters if you want to build it rather than install it:
androidApp/
desktopApp/
webApp/
shared/
web-capture/For contributors there is a Development Guide in DEVELOPMENT.md and a Contributing Guide in CONTRIBUTING.md, along with a Code of Conduct in the organisation's .github repository. The Gradle Wrapper is checked in as gradlew and gradlew.bat, so a source build uses the pinned Gradle version rather than a system install. The kotlin-js-store/ directory is the Yarn lockfile store for the JavaScript target, and fastlane/ is present for the store release pipeline.
The desktop capture workflow has its own note. If you only want to save pages on desktop, the README points to the kapture GUI, whose releases are published separately, and states that Linkora uses its core library. In other words, the page-saving engine is a library with its own desktop front end, and Linkora is the multiplatform application built on top of it.
Local HTML capture is where the privacy claim lives
The way Linkora captures a page is the part that determines whether the local-first description holds up.
The README states that all processing happens completely on your device. Combined with the stack, that means the page is fetched by the app, parsed by Ksoup, and written out as a standalone HTML file with images handled through Coil, without an intermediate server. The web-capture/ directory in the repository is the module that does it.
The metadata extraction is what makes saved pages navigable later. Ksoup is used for HTML parsing and metadata extraction, and the feature list separately notes that link metadata can be customised and that images and titles are auto-recognised from web pages. So a saved link is not just a URL string with a title typed by hand; the app pulls what it can from the page itself.
The caveat is the same one every archiving tool has, and the README does not hide it: a page that needs a login, or that loads its content through JavaScript after the initial response, may not capture completely, because there is no headless browser in the stack to execute it. What you get is what the server returned to your client at fetch time. That is fine for a documentation page and less fine for an application-style site.
The bulk metadata refresh on Android, scheduled through WorkManager, is the second half of this story. It re-fetches pages for existing links so titles and thumbnails stay current, and doing that in the background is what keeps a large library from needing a manual refresh.
Remote localisation strings and a fast release cadence
Linkora supports multiple languages with remote strings that can be updated without requiring an app update, described as over-the-air updates. The locales/ directory holds the local resources, and a separate localization-server repository holds the process, whose README explains how localisation is handled and how to contribute a translation.
This is a deliberate trade. Remote strings let a translator fix a wording mistake and have it reach users without waiting for a store review, and it means the localisation pipeline is infrastructure the project depends on. It also means the app fetches text from a server the author controls, so a reader who wants to know exactly what their client will display has to look at that server. For a bookmark manager that is a small exposure, but it is worth naming.
The release record shows a steady cadence. The recent releases are release-v0.22.0 on 2026-09-30, preview-v0.22.0 on 2026-09-28 and release-v0.21.0 on 2026-09-12, and the repository is not archived with the last push on 2026-10-09. A preview tag ahead of the matching release tag is a pattern worth noticing: the preview build is how the author ships a version for testing before the release build is cut.
The licence field on the repository says MIT, and the README ends with the same statement. For an application with a MIT licence, the obligations on redistribution are light, and unlike the sync server or the browser extension, those pieces carry their own terms that you would check separately.
Editorial conclusion
Linkora suits people who want one bookmark library across Android, desktop and web without handing their reading list to a hosted service, and who are willing to run a sync server if they want their devices to converge. It does not suit anyone who expects turnkey multi-device sync, since the sync server is a separate repository you have to deploy and configure yourself, and it does not suit a workflow that needs shared links with colleagues. Before adopting, install it on one device and check that the import and export in JSON and HTML formats carries your existing bookmarks, then read docs/ServerConnectionSetup.md before assuming two devices will sync.
Frequently asked questions
What is Linkora and which platforms does it run on?
Linkora is a local-first link organiser built with Kotlin Multiplatform, Compose Multiplatform and Material 3 that saves, organises and syncs links between Android, desktop and web. Its data is stored locally in SQLite through Room, with sync only when you run your own server.
How do I install Linkora?
The README links a GitHub releases page, F-Droid under the package id com.sakethh.linkora, Google Play, and an Arch User Repository package named linkora-bin. Desktop and web builds are published through the same releases stream.
Does Linkora need an account or a server to work?
No, the sync is optional. The README describes an optional self-hostable sync-server, and the server setup instructions live in docs/ServerConnectionSetup.md, so a server is only needed if you want your devices to converge.
How does Linkora save a webpage?
It saves pages as standalone HTML files, with all processing happening completely on your device, using the kapture library and Ksoup for parsing and metadata extraction. The same engine is available on its own as the kapture GUI for desktop only.
Can Linkora import my existing bookmarks?
The feature list includes sorting, searching, import and export of data in JSON and HTML formats with auto-backups. The README does not specify which bookmark formats are accepted, so check that before migrating a large existing collection.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/linkoraapp-linkora)Was this useful?