docs: Initial Documentation
This commit is contained in:
@@ -0,0 +1,42 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
Context file for Claude Code. Read this before making changes. See `docs/ARCHITECTURE.md` for deep technical rationale.
|
||||||
|
|
||||||
|
## Project
|
||||||
|
|
||||||
|
Native Apple ecosystem client for a self-hosted [Outline](https://github.com/outline/outline) instance (wiki/knowledge base). Targets **iOS, iPadOS, macOS**, single SwiftUI multiplatform codebase. Goal is **full editing parity** with Outline's web app — not a read-only viewer.
|
||||||
|
|
||||||
|
Working name: `OutlineClient` (rename freely — placeholder only, not a branding decision).
|
||||||
|
|
||||||
|
## License context (do not re-litigate)
|
||||||
|
|
||||||
|
Outline server is BSL 1.1 licensed. This restricts *hosting/reselling Outline itself as a service*. It does **not** restrict building an API client. This app only ever talks to Outline's public REST/WebSocket API — it never vendors, forks, or redistributes Outline's server source. No license concerns for this codebase.
|
||||||
|
|
||||||
|
## Architecture summary
|
||||||
|
|
||||||
|
- **REST layer** — Outline's RPC-style API (`/api/*`), Bearer token auth (`Authorization: Bearer <token>`). Handles collections, documents (non-realtime CRUD), search, users.
|
||||||
|
- **Realtime collab layer** — Outline runs a **Hocuspocus** server (Yjs CRDT over WebSocket) at `wss://<host>/collaboration/document.<id>`. This is the actual editing transport when a document is open — not the REST API. Full parity requires speaking this protocol, including the Yjs awareness protocol for remote cursors/presence.
|
||||||
|
- **CRDT engine** — [YSwift](https://github.com/y-crdt/yswift) (Swift bindings over `yrs`, the Rust Yjs port, via UniFFI). This is the only realistic native path to binary-compatible Yjs sync. It is pre-1.0 / WIP — expect to patch or contribute upstream, don't assume full feature coverage going in.
|
||||||
|
- **Editor UI** — native TextKit 2 (`NSTextLayoutManager` / `AttributedString`) rendering mapped from Outline's ProseMirror document schema (headings, lists, checklists, tables, code blocks, embeds, comments). This is the largest single scope item in the project — treat it as its own subsystem, not a UI detail.
|
||||||
|
|
||||||
|
## Phased build order
|
||||||
|
|
||||||
|
1. **Phase 1 — Read/browse + REST-only editing.** Auth, collections tree, document list, search, markdown-rendered read view, basic edit-and-PUT (last-write-wins, no live collab). Ship this before touching Yjs at all.
|
||||||
|
2. **Phase 2 — Realtime collaboration.** Integrate YSwift + Hocuspocus WebSocket, map Yjs XML fragment ↔ native editor state, add awareness/presence.
|
||||||
|
3. **Phase 3 — Polish.** Offline cache, conflict UI, embeds/attachments, tables, comments, macOS-specific affordances (menu bar, multiple windows).
|
||||||
|
|
||||||
|
Do not start Phase 2 work until Phase 1 is stable and shipped to the device. The CRDT/editor layer is high-risk; de-risk everything else first.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Swift, SwiftUI-first. No UIKit/AppKit escape hatches unless SwiftUI genuinely can't do it (flag these explicitly in PR/commit messages).
|
||||||
|
- Networking: `URLSession` + `async/await`, no third-party HTTP client.
|
||||||
|
- API tokens stored in Keychain only — never UserDefaults, never logged.
|
||||||
|
- Prefer protocol-oriented boundaries between the REST layer, the CRDT/sync layer, and the editor UI layer so any one of them (especially YSwift) can be swapped without touching the others.
|
||||||
|
- Target iOS 17+ / macOS 14+ minimum (needed for mature `AttributedString`/TextKit 2 APIs).
|
||||||
|
|
||||||
|
## Do not
|
||||||
|
|
||||||
|
- Do not attempt to reimplement Yjs's CRDT algorithm from scratch — use YSwift/yrs. This has been tried by others and is a multi-year effort (see Yrs project history).
|
||||||
|
- Do not fall back to polling the REST API for "realtime" — it will visibly diverge from true collaborative editing and defeats the point of this project.
|
||||||
|
- Do not vendor or copy Outline's server source into this repo.
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 Puranjay Savar Mattas
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Outpost
|
||||||
|
|
||||||
|
A native Apple ecosystem client for [Outline](https://github.com/outline/outline) — built for iOS, iPadOS, and macOS from a single SwiftUI codebase, aiming for full editing parity with Outline's web app, including realtime collaborative editing.
|
||||||
|
|
||||||
|
## Why
|
||||||
|
|
||||||
|
Outline's web app is great, but there's no native Apple client with full editing parity. This project connects to a self-hosted Outline instance over its REST API and realtime collaboration socket to provide a proper native experience across the Apple ecosystem.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Early development. See `CLAUDE.md` for the current architecture and phased build plan.
|
||||||
|
|
||||||
|
- [ ] Phase 1 — Auth, browse, search, REST-only editing
|
||||||
|
- [ ] Phase 2 — Realtime collaborative editing (Yjs/Hocuspocus)
|
||||||
|
- [ ] Phase 3 — Offline cache, tables, embeds, comments, macOS polish
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Xcode 16+
|
||||||
|
- iOS 17+ / iPadOS 17+ / macOS 14+
|
||||||
|
- A self-hosted (or hosted) Outline instance with API access
|
||||||
|
|
||||||
|
> They will be updated. These are old requirements.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. Clone the repo and open the `.xcodeproj` in Xcode.
|
||||||
|
2. Generate a scoped API key on your Outline instance (Settings → API Keys).
|
||||||
|
3. On first launch, enter your instance URL and API key — these are stored in Keychain, never in app config or source.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
See [`CLAUDE.md`](./CLAUDE.md) and [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md) for the full technical breakdown: REST layer, Yjs/Hocuspocus realtime sync via [YSwift](https://github.com/y-crdt/yswift), and the ProseMirror-schema-to-native-editor mapping.
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
This project is being built to solve a personal problem — I wanted a genuinely good native knowledge-base client for my own self-hosted Outline instance and none of the existing options fit. It's a personal-use tool first, not a polished product with support guarantees.
|
||||||
|
|
||||||
|
Parts of this codebase are AI-assisted (built with the help of AI coding tools). Treat that however you like — review, use, fork, or ignore the code accordingly. No warranty of quality, security, or fitness for any particular use is implied beyond what's stated in the license below.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is a client only — it does not include, vendor, or redistribute any of Outline's (BSL 1.1 licensed) server source. See [`LICENSE`](./LICENSE) for this repository's own license.
|
||||||
|
|
||||||
|
## Not affiliated with Outline
|
||||||
|
|
||||||
|
This is an independent, unofficial client. Not affiliated with or endorsed by General Outline, Inc.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# Architecture Notes
|
||||||
|
|
||||||
|
Deeper technical reference backing `CLAUDE.md`. Update this as decisions are made — treat it as a living design doc, not a one-time spec.
|
||||||
|
|
||||||
|
## 1. Outline API surface
|
||||||
|
|
||||||
|
- **Base**: `https://<your-instance>/api/*`, RPC-style (POST for nearly everything, not strict REST verbs).
|
||||||
|
- **Auth**: `Authorization: Bearer <API_KEY>` header. Keys are created per-user under Settings → API Keys on the Outline instance. Store in Keychain, scope a dedicated key to this app rather than reusing a personal one.
|
||||||
|
- **Core endpoints to wrap first**: `documents.info`, `documents.list`, `documents.search`, `documents.create`, `documents.update`, `collections.list`, `collections.info`, `users.info`.
|
||||||
|
- Full reference: your instance's `/developers` page (same docs as getoutline.com/developers, versioned per Outline release — check against your self-hosted version, not just the public docs).
|
||||||
|
|
||||||
|
## 2. Realtime collaboration transport
|
||||||
|
|
||||||
|
- Endpoint: `wss://<your-instance>/collaboration/document.<document-id>`.
|
||||||
|
- Protocol: Hocuspocus (a Yjs-CRDT-over-WebSocket server implementation). This is **not** the same socket as any notification/presence channel — it's the actual document edit transport.
|
||||||
|
- Payload: binary Yjs update messages (Yjs update format v1/v2) plus the Yjs awareness protocol for cursor/selection presence.
|
||||||
|
- Your reverse proxy (Caddy, in your homelab) must forward `Upgrade`/`Connection` headers correctly or collaboration silently falls back to "no live sync" while REST edits still work — worth a smoke test against your own Caddy config early.
|
||||||
|
|
||||||
|
## 3. CRDT engine — YSwift
|
||||||
|
|
||||||
|
- Repo: `y-crdt/yswift`. Swift bindings over `yrs` (Rust) via UniFFI, distributed with a prebuilt XCFramework.
|
||||||
|
- Status as of mid-2026: WIP, pre-1.0, small but active contributor base. Not all Yrs/Yjs features are exposed yet.
|
||||||
|
- Integration point: YSwift gives you a local `Y.Doc` you mutate; a Hocuspocus-compatible WebSocket provider (you'll likely need to write this provider yourself in Swift — no off-the-shelf Swift Hocuspocus client exists yet) syncs that doc's binary updates with the server.
|
||||||
|
- Fallback if YSwift blocks progress: vendor the C FFI (`yffi`) directly and write a thinner Swift wrapper for just the operations you need (XML fragment read/write, update encode/decode, state vector diffing).
|
||||||
|
|
||||||
|
## 4. Document schema mapping
|
||||||
|
|
||||||
|
Outline's editor is ProseMirror-based; the Yjs doc stores document structure as a `Y.XmlFragment` mirroring the ProseMirror schema (paragraphs, headings, bullet/ordered/checklist lists, tables, code blocks, blockquotes, embeds, comments-as-marks). Native editor work breaks into:
|
||||||
|
|
||||||
|
- **Read path**: Y.XmlFragment → your own document model → `AttributedString`/TextKit 2 layout.
|
||||||
|
- **Write path**: local edit → diff against your document model → Yjs transaction on the XmlFragment → binary update sent over the Hocuspocus socket.
|
||||||
|
- Build the node-type mapping table (ProseMirror node/mark name → native representation) as an explicit, tested module — this is the piece most likely to silently drift from Outline's actual schema as Outline ships updates.
|
||||||
|
|
||||||
|
## 5. Known risk areas (revisit as the project progresses)
|
||||||
|
|
||||||
|
- YSwift feature gaps vs. full Yjs (undo/redo manager, relative positions) — check current state before Phase 2 starts, this library moves fast.
|
||||||
|
- Table and embed support are the least standardized part of ProseMirror schemas generally — budget them last.
|
||||||
|
- Outline server version drift: self-hosted instance upgrades could change API shapes or the collaboration payload; pin against your actual running version, not assumptions from docs.
|
||||||
Reference in New Issue
Block a user