Files
linkding-ios/openwiki/quickstart.md
Krishna Kumar 4d875e12d6
All checks were successful
CI / build-and-deploy (push) Successful in 17s
add openwiki docs
2026-07-02 00:33:49 -05:00

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 /Marks with SwiftUI tabs for bookmarks, tags, podcasts, and search. The entrypoint is /Marks/MarksApp.swift.
  • Models in /Marks/Models, centered on Bookmark, linkding response/create/update payloads, tags, smart collections, and ServerConfig.
  • Services in /Marks/Services for linkding networking, AI/backend calls, auth, on-device bookmark Q&A, Spotlight indexing, widget/podcast data, analytics, and logging.
  • Views in /Marks/Views for the primary product surfaces. BookmarksViewModel is the central app state object.
  • App Intents in /Marks/Intents for opening, searching, adding, listing unread, and summarizing bookmarks.
  • Share extension in /ShareExtension for saving shared URLs/text to linkding and queueing podcast generation.
  • Widget extension in /MarksWidget for 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.xcodeproj is generated/checked in but project.yml is the project definition to inspect first.
  • Design notes in /docs/design-wwdc26.md for 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. LinkdingAPI uses token auth and calls linkding bookmark, check, tag, create, update, delete, archive, and connection-test endpoints.
  • Marks backend is used by MarksAuth/ClaudeService for 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 the BookmarkSearchTool retrieval 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 via FoundationModels. Prefer source evidence when changing AI behavior.
  • OnboardingView exists, 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.
  • BookmarksViewModel is 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.