mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 183 lines 7.5 kB view raw view rendered
1# Development Guide 2 3## Quick Start 4 5```sh 6flutter pub get 7just objectbox-setup # once per machine (macOS/Linux) 8just gen 9flutter run 10``` 11 12## Common Tasks 13 14Use `just` for common workflows: 15 16| Command | Description | 17| ---------------------- | ----------------------------------------------------- | 18| `just format` | Run `dart format` | 19| `just lint` | Run `flutter analyze` | 20| `just objectbox-setup` | Install pinned ObjectBox native runtime (macOS/Linux) | 21| `just objectbox-check` | Verify ObjectBox native runtime is present | 22| `just test` | Run the full `flutter test` suite | 23| `just gen` | Run `build_runner` for code generation | 24| `just check` | Format, lint, and test in sequence | 25 26## Architecture 27 28### Stack 29 30| Layer | Technology | 31| ---------------- | ------------------------------------------------------------- | 32| Framework | Flutter (Material 3) | 33| State management | `flutter_bloc` (Bloc + Cubit) | 34| Primary database | Drift (SQLite) — source of truth | 35| Vector store | ObjectBox — embeddings for semantic search | 36| Networking | `bluesky` / `atproto` packages + Dio | 37| Navigation | `go_router` (StatefulShellRoute) | 38| Code generation | `build_runner`, `freezed`, `drift_dev`, `objectbox_generator` | 39 40### Feature Module Layout 41 42Each feature follows this convention: 43 44```sh 45features/<feature>/ 46 bloc/ # Bloc or Cubit + State + Event classes 47 cubit/ # Lighter-weight cubits where appropriate 48 data/ # Repository classes; API + database interactions 49 presentation/ 50 <feature>_screen.dart 51 widgets/ 52``` 53 54## Database 55 56### Drift (primary store) 57 58Powered by **Drift** (SQLite). All migrations live in `lib/core/database/app_database.dart`. 59 60Current schema version: **15** 61 62| Table | Version | Purpose | 63| ------------------- | ------- | -------------------------------------------------------- | 64| `accounts` | 1 | Auth sessions (DID, tokens, handle, service URL) | 65| `cached_profiles` | 2 | Profile metadata cache | 66| `cached_posts` | 2 | Post content cache for offline display | 67| `settings` | 1 | Key-value application configuration | 68| `saved_feeds` | 3 | User's pinned and saved feeds | 69| `cached_feed_pages` | 12 | First-page feed cache for cold-start UX | 70| `search_history` | 4 | Persistent local search query history | 71| `drafts` | 5 | Offline-first post drafts with media | 72| `saved_posts` | 6 | Locally saved posts (save type: local or cloud bookmark) | 73| `labeler_cache` | 9 | Cached labeler service policies | 74| `liked_posts` | 15 | Locally persisted liked posts for semantic search | 75 76#### Adding a migration 77 781. Add or modify table definition in `lib/core/database/tables.dart`. 792. Bump `schemaVersion` in `AppDatabase`. 803. Add `if (from < N) { ... }` block in `MigrationStrategy.onUpgrade`. 814. Run `just gen` to regenerate `app_database.g.dart`. 82 83### ObjectBox (vector store) 84 85ObjectBox runs as a secondary store alongside Drift. It holds only embedding vectors and the metadata needed to join back to Drift. 86 87The `EmbeddedPost` entity stores: 88 89- `postUri` (unique AT-URI) 90- `accountDid` 91- `source` (`'saved'` or `'liked'`) 92- `indexedText` — text used to produce the embedding 93- `embedding` — 384-dimensional float32 vector (HNSW cosine index) 94- `embeddedAt` 95 96After modifying `EmbeddedPost`, run `just gen` to regenerate `objectbox.g.dart` and `objectbox-model.json`. 97 98#### Running unit tests (ObjectBox native library) 99 100ObjectBox requires a platform native library to run `flutter test` locally. 101Lazurite standardizes this setup through a pinned installer script. 102 103Supported local platforms: macOS and Linux. 104 105Run this once per machine: 106 107```sh 108just objectbox-setup 109``` 110 111`just test` and `just test-quiet` intentionally run a preflight check 112(`just objectbox-check`) and fail fast with setup instructions if the 113runtime is missing. 114 115## Semantic Search 116 117On-device vector search over saved and liked posts using: 118 119- **Model:** `all-MiniLM-L6-v2` quantized INT8 TFLite model (384D output, ~25 MB) 120- **Tokenizer:** WordPiece, max 256 tokens, bundled as Flutter assets 121- **Inference:** Long-lived background `Isolate` via `EmbeddingService` 122- **Storage:** ObjectBox with HNSW cosine index on the embedding vector 123 124The `EmbeddingService.isAvailable` flag gates all semantic search UI entry points. On initialization failure the feature degrades gracefully to unavailable. 125 126## Liked Posts 127 128Liked posts are synced from the Bluesky API and persisted locally in the `liked_posts` Drift table. This feeds the semantic search pipeline. 129 130**`LikedPostsRepository`** (`lib/features/feed/data/liked_posts_repository.dart`): 131 132| Method | Description | 133| -------------------------------------------- | ----------------------------------------------------------------------------- | 134| `syncLikes(accountDid)` | Paginate `getActorLikes` until a known URI is hit or 1000-post cap is reached | 135| | evicts oldest on overflow | 136| `getLikedPosts(accountDid, {limit, offset})` | Paginated query ordered by `likedAt DESC` | 137| `removeLike(accountDid, postUri)` | Delete a single entry | 138 139## Testing 140 141Run the full suite: 142 143```sh 144just test 145# or with failure-only reporter (recommended for large suites): 146just test-quiet 147``` 148 149Coverage target: **>99%** (±5% acceptable). All new code must have tests. Widget tests use `NativeDatabase.memory()` for Drift and mocktail for API mocks. 150 151## Code Generation 152 153Run after any change to: 154 155- Drift table definitions (`tables.dart`) 156- ObjectBox entities (`embedded_post.dart`) 157- `freezed` models 158- `json_serializable` classes 159 160```sh 161just gen 162# or: 163dart run build_runner build --delete-conflicting-outputs 164``` 165 166## Routes 167 168| Path | Description | 169| ----------- | ------------------------------ | 170| `/login` | Authentication gateway | 171| `/` | Home feed tab | 172| `/search` | Search tab | 173| `/profile` | Current user profile tab | 174| `/settings` | Global settings | 175| `/compose` | Root-level modal for new posts | 176 177## References 178 179- [Bluesky API Documentation](https://docs.bsky.app/) 180- [AT Protocol Specification](https://atproto.com/) 181- [Flutter Documentation](https://flutter.dev/docs) 182- [Drift Documentation](https://drift.simonbinder.eu/) 183- [ObjectBox Flutter](https://docs.objectbox.io/flutter)