7.1 KiB
Marks OpenWiki Quickstart
Marks is a native SwiftUI iOS client for linkding, a self-hosted bookmark manager. The app targets iOS 26 and Swift 6, and includes a main app, share extension, widget extension, App Intents, AI-assisted bookmark features, and podcast generation/playback.
Start here when changing the repository, then follow the page links below for the area you are touching.
What this repository contains
- Main iOS app in
/Markswith SwiftUI tabs for bookmarks, tags, podcasts, and search. The entrypoint is/Marks/MarksApp.swift. - Models in
/Marks/Models, centered onBookmark, linkding response/create/update payloads, tags, smart collections, andServerConfig. - Services in
/Marks/Servicesfor linkding networking, AI/backend calls, auth, on-device bookmark Q&A, Spotlight indexing, widget/podcast data, analytics, and logging. - Views in
/Marks/Viewsfor the primary product surfaces.BookmarksViewModelis the central app state object. - App Intents in
/Marks/Intentsfor opening, searching, adding, listing unread, and summarizing bookmarks. - Share extension in
/ShareExtensionfor saving shared URLs/text to linkding and queueing podcast generation. - Widget extension in
/MarksWidgetfor recent bookmarks, random bookmark, and recent podcast widgets. - Tests in
/MarksTests, currently focused on the App Intents layer. - XcodeGen project spec in
/project.yml;Marks.xcodeprojis generated/checked in butproject.ymlis the project definition to inspect first. - Design notes in
/docs/design-wwdc26.mdfor iOS 26/Liquid Glass, search, widgets, and row-design guidance.
Major documentation pages
- Architecture notes — target layout, state flow, networking, persistence, AI, Spotlight, extensions, widgets, and App Intents.
- Product workflows — how bookmark browsing, saving, AI enrichment, Ask, smart collections, podcasts, widgets, and intents behave.
- Development and testing — setup/build/test commands, generated project guidance, storage/config map, verification checklist, and caveats.
Build and run
The README documents the intended local setup:
brew install xcodegen
xcodegen generate
open Marks.xcodeproj
Then build and run from Xcode using the Marks scheme. /project.yml defines Swift 6.0, iOS 26.0 deployment target, the Marks, ShareExtension, MarksWidget, and MarksTests targets, and the app-group entitlements used by all app surfaces.
Useful checks before shipping a change:
xcodegen generate
xcodebuild test -scheme Marks -destination 'platform=iOS Simulator,name=iPhone 16'
Adjust the simulator name to what is installed locally.
Runtime architecture in one minute
At launch, MarksApp loads a ServerConfig, constructs LinkdingAPI, and stores a shared BookmarksViewModel in MainContainer so it survives SwiftUI re-renders (/Marks/MarksApp.swift, /Marks/Views/BookmarksViewModel.swift). The top-level TabView has Bookmarks, Tags, Podcasts, and Search tabs.
BookmarksViewModel fetches paginated bookmarks from linkding through LinkdingAPI, restores local AI metadata, caches bookmarks to Application Support, writes recent bookmark metadata for widgets, and indexes bookmarks into Spotlight. It also owns ClaudeService, PodcastPlayerViewModel, and PodcastGenerationManager, so AI, podcast, search, and list state are shared across tabs.
Extensions and widgets use the shared app group group.com.magicive.marks. ServerConfig.save() writes to standard defaults and the app-group defaults; WidgetDataStore writes app-group JSON files for widgets; PodcastRequests uses app-group defaults to hand podcast requests from the share extension to the main app.
External systems and privacy boundaries
- linkding is the source of truth for bookmarks and tags.
LinkdingAPIuses token auth and calls linkding bookmark, check, tag, create, update, delete, archive, and connection-test endpoints. - Marks backend is used by
MarksAuth/ClaudeServicefor AI enrichment, semantic search, smart collections, analytics events, and podcast generation/audio download. - Apple on-device intelligence and Spotlight power the in-app Ask surface via
FoundationModels,CoreSpotlight, and theBookmarkSearchToolretrieval path. - WidgetKit, App Intents, AVFoundation, and MediaPlayer support widgets, Siri/Shortcuts integration, podcast playback, background audio, now-playing metadata, and remote controls.
Do not document or expose secret values. /Marks/MarksApp.swift currently contains a built-in default server configuration with a token-like value; treat it as sensitive source material and avoid copying it into docs, logs, screenshots, or tests.
Important caveats for future agents
- The README says optional AI features use OpenRouter/Gemini directly. Current source routes backend AI/podcast calls through
MarksAuth+ClaudeService; the in-app Ask feature is on-device viaFoundationModels. Prefer source evidence when changing AI behavior. OnboardingViewexists, but current launch flow uses saved-or-default config directly. Do not assume onboarding is active without changing/Marks/MarksApp.swift.- Settings' disconnect callback currently resets to the built-in default config path rather than forcing onboarding. Confirm intended product behavior before changing account/config flows.
BookmarksViewModelis shared across tabs, so changes to bookmark arrays, filters, search, enrichment, and pagination can affect Bookmarks, Tags, Search, Podcasts, widgets, and Spotlight indexing.- Share-extension podcast requests are queued in shared defaults and drained by the main app on launch/foreground. Be careful with crash/retry semantics when touching that flow.
- Existing automated tests cover App Intents only. For UI, networking, sync, share extension, widgets, and podcasts, add tests where feasible and perform manual verification.
Where to start for common changes
- Bookmark list, pagination, search, tags, enrichment state:
/Marks/Views/BookmarksViewModel.swift,/Marks/Views/BookmarksView.swift,/Marks/Services/LinkdingAPI.swift. - Linkding API changes:
/Marks/Services/LinkdingAPI.swift,/Marks/Models/Bookmark.swift,/ShareExtension/ShareView.swift,/Marks/Intents/IntentSupport.swift. - AI/backend changes:
/Marks/Services/ClaudeService.swift,/Marks/Services/MarksAuth.swift,/Marks/Services/BookmarkAssistant.swift,/Marks/Services/BookmarkSearchTool.swift. - Podcast generation/playback:
/Marks/Services/PodcastGenerationManager.swift,/Marks/Services/PodcastIndex.swift,/Marks/Views/PodcastPlayerView.swift,/Marks/Views/BookmarksViewModel.swift. - Share extension:
/ShareExtension/ShareViewController.swift,/ShareExtension/ShareView.swift,/ShareExtension/TagSuggester.swift, plus shared files declared in/project.yml. - Widgets/deep links:
/MarksWidget/WidgetDataStore.swift,/MarksWidget/*Widget.swift,/Marks/MarksApp.swift. - App Intents/Siri/Shortcuts:
/Marks/Intents/*,/MarksTests/AppIntentsTests.swift.