Replace Flutter app with native SwiftUI rewrite (iOS 26)
Complete ground-up rewrite in SwiftUI targeting iOS 26. Drops the Flutter/Dart codebase entirely in favour of a lean native app with no third-party dependencies. Features shipped: - Bookmark list with pagination, pull-to-refresh, swipe delete/archive - Add bookmark form + iOS share extension (zero-tap save from any app) - Tags tab — all tags sorted by count, tap to browse filtered bookmarks - Native search tab (Tab role: .search) with instant client-side filtering - AI enrichment via OpenRouter (google/gemini-2.0-flash-lite-001): auto-summary and tag generation, semantic search, smart collections - Settings: linkding server config, OpenRouter API key - App Groups for credential sharing between main app and share extension - Swift 6 strict concurrency throughout (@Observable, @MainActor) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
112
README.md
112
README.md
@@ -1,61 +1,69 @@
|
||||
<h1 align="center">
|
||||
<img src="assets/other/banner.png" />
|
||||
</h1>
|
||||
# Marks
|
||||
|
||||
<p align="center">
|
||||
<b>Linkdy</b> is a <a href="https://github.com/sissbruecker/linkding" target="_blank" rel="noopener noreferrer"><b>Linkding</b></a> client created with Flutter. <a href="https://github.com/sissbruecker/linkding" target="_blank" rel="noopener noreferrer">Linkding</a> is a self hosted bookmark manager. The objective of this project is to give all it's users an application to manage the bookmarks from a mobile device.
|
||||
</p>
|
||||
A native iOS client for [linkding](https://github.com/sissbruecker/linkding), the self-hosted bookmark manager.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://play.google.com/store/apps/details?id=com.jgeek00.linkdy" target="_blank" rel="noopener noreferrer">
|
||||
<img src="/assets/other/get_google_play.png" width="300px">
|
||||
</a>
|
||||
<a href="https://apps.apple.com/us/app/linkdy/id6479930976" target="_blank" rel="noopener noreferrer">
|
||||
<img src="/assets/other/get-appstore.png" width="300px">
|
||||
</a>
|
||||
</p>
|
||||
Built from scratch in SwiftUI targeting iOS 26. Replaces the previous Flutter-based app.
|
||||
|
||||
### Main features
|
||||
<ul>
|
||||
<li>List your bookmarks.</li>
|
||||
<li>Open the links on an internal browser.</li>
|
||||
<li>Search bookmarks.</li>
|
||||
<li>Create new bookmarks.</li>
|
||||
<li>Create new tags.</li>
|
||||
<li>List the bookmarks associated with each tag.</li>
|
||||
<li>Material You interface with dynamic theming (only Android 12+).</li>
|
||||
</ul>
|
||||
## Features
|
||||
|
||||
## Privacy policy
|
||||
Check the privacy policy [here](https://pastebin.com/raw/Yiw4h6KK).
|
||||
- Browse and search your bookmarks
|
||||
- Swipe to delete or archive
|
||||
- Add bookmarks manually
|
||||
- Share to Marks from any app (share extension)
|
||||
- Tag browser — see all tags sorted by count, tap to filter
|
||||
- Native search tab with instant client-side filtering
|
||||
- AI enrichment via OpenRouter — auto-generates summaries and tags for each bookmark
|
||||
- Semantic search — rank bookmarks by relevance using AI
|
||||
- Smart Collections — AI groups your bookmarks into themed collections
|
||||
- Pagination — loads more as you scroll
|
||||
|
||||
### Development
|
||||
1. Clone this repository.
|
||||
2. Run ``flutter pub get`` to install all the dependencies.
|
||||
3. Run the application on the desired virtual or physical device.
|
||||
## Requirements
|
||||
|
||||
<p>
|
||||
<b>State manager</b>
|
||||
<br>
|
||||
Linkdy uses Riverpod as the state management system. Files ended on <code>.g.dart</code> are auto generated by Riverpod's code generator and shouldn't be edited manually.
|
||||
The code generator can be started by running <code>dart run build_runner watch</code>. Then, the process will start on the terminal.
|
||||
</p>
|
||||
<p>
|
||||
<b>Translations</b>
|
||||
<br>
|
||||
Linkdy uses <a href="https://pub.dev/packages/slang">slang</a> to manage the translations of the application. To add a new translation, create a new file on <code>lib/i18n</code>, with the structure <code>strings_[lang_code].i18n.json</code>. When adding a new string, make sure to add the translation on all <code>.i18n.json</code> files. Then, run <code>dart run slang</code> to generate the translations.
|
||||
</p>
|
||||
- iOS 26+
|
||||
- A running [linkding](https://github.com/sissbruecker/linkding) instance with API access
|
||||
- (Optional) An [OpenRouter](https://openrouter.ai) API key for AI features
|
||||
|
||||
### Android signing
|
||||
1. Clone ``android/key.properties.sample`` and rename it to ``key.properties``.
|
||||
2. Fill the variables with the values.
|
||||
3. Put your ``keystore.jks`` file inside ``android/app/``.
|
||||
4. Run ``flutter build apk --release`` or ``flutter build appbundle --release`` to compile and sign the production build.
|
||||
## AI Features
|
||||
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
All AI features are optional and powered by [OpenRouter](https://openrouter.ai) using `google/gemini-2.0-flash-lite-001` — one of the cheapest available models (~$0.075/M input tokens).
|
||||
|
||||
##### Created by JGeek00
|
||||
| Feature | What it does |
|
||||
|---|---|
|
||||
| Auto-enrichment | Generates a one-sentence summary and 3-5 tags for each bookmark |
|
||||
| Semantic search | Ranks your bookmarks by relevance to a natural language query |
|
||||
| Smart Collections | Groups up to 150 bookmarks into 3-6 themed collections |
|
||||
|
||||
Add your OpenRouter API key in Settings to enable these features.
|
||||
|
||||
## Building
|
||||
|
||||
Requires [xcodegen](https://github.com/yonaskolb/XcodeGen).
|
||||
|
||||
```bash
|
||||
brew install xcodegen
|
||||
xcodegen generate
|
||||
open Marks.xcodeproj
|
||||
```
|
||||
|
||||
Then build and run in Xcode. The project uses automatic signing — set your development team in `project.yml` under `DEVELOPMENT_TEAM`.
|
||||
|
||||
## Architecture
|
||||
|
||||
- **SwiftUI** with `@Observable` and `@MainActor` throughout (Swift 6 strict concurrency)
|
||||
- **LinkdingAPI** — thin wrapper around the linkding REST API
|
||||
- **ClaudeService** — OpenRouter client for AI enrichment, semantic search, and collections
|
||||
- **BookmarksViewModel** — central state: bookmarks list, pagination, search, enrichment progress
|
||||
- **App Groups** — share extension and main app share credentials via `group.com.magicive.marks`
|
||||
- **UserDefaults** — AI summaries and tags cached locally by bookmark ID
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
Marks/
|
||||
Models/ Bookmark, ServerConfig, SmartCollection
|
||||
Services/ LinkdingAPI, ClaudeService
|
||||
Views/ BookmarksView, TagsView, SearchView, SettingsView, …
|
||||
Assets.xcassets App icon and assets
|
||||
ShareExtension/ iOS share extension (zero-tap bookmark saving)
|
||||
project.yml xcodegen project spec
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user