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

82 lines
7.1 KiB
Markdown

# Marks OpenWiki Quickstart
Marks is a native SwiftUI iOS client for [linkding](https://github.com/sissbruecker/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](architecture/app-architecture.md) — target layout, state flow, networking, persistence, AI, Spotlight, extensions, widgets, and App Intents.
- [Product workflows](workflows/product-workflows.md) — how bookmark browsing, saving, AI enrichment, Ask, smart collections, podcasts, widgets, and intents behave.
- [Development and testing](operations/development-and-testing.md) — setup/build/test commands, generated project guidance, storage/config map, verification checklist, and caveats.
## Build and run
The README documents the intended local setup:
```bash
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:
```bash
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`.