# Quickstart This guide walks through a full in-memory repository lifecycle: 1. Start blockstore 2. Create repo 3. Write records 4. Query records 5. Verify integrity 6. Export/import with CAR ## 1) Start Store And Keys ```elixir alias Potable.{BlockStore, Signing} {:ok, store} = BlockStore.Memory.start_link() {pub, priv} = Signing.generate_keypair() did = "did:plc:quickstart1234567890" ``` ## 2) Create Repository ```elixir alias Potable.Repository {:ok, head0} = Repository.create_repo(did, priv, store) ``` `create_repo/3` creates: - an empty MST root block - a signed genesis commit (no `"prev"` field) - a returned head CID for the new commit ## 3) Apply Writes Writes are tuples: - `{:create, collection, rkey, record_map}` - `{:update, collection, rkey, record_map}` - `{:delete, collection, rkey}` ```elixir post_1 = %{ "$type" => "app.bsky.feed.post", "text" => "first post", "createdAt" => "2026-02-13T00:00:00Z" } post_2 = %{ "$type" => "app.bsky.feed.post", "text" => "second post", "createdAt" => "2026-02-13T00:01:00Z" } {:ok, head1} = Repository.apply_writes( head0, did, [ {:create, "app.bsky.feed.post", "post-1", post_1}, {:create, "app.bsky.feed.post", "post-2", post_2} ], priv, store ) ``` Potable accepts atom-keyed record maps on input and converts keys to strings. Read APIs always return string-keyed maps. ## 4) Read Records ```elixir {:ok, one_post} = Repository.get_record(head1, "app.bsky.feed.post", "post-1", store) {:ok, posts} = Repository.list_records(head1, "app.bsky.feed.post", [limit: 100], store) ``` `list_records/4` supports: - `limit: n` - `after: rkey` ## 5) Update And Delete ```elixir updated = Map.put(post_1, "text", "first post (edited)") {:ok, head2} = Repository.apply_writes( head1, did, [ {:update, "app.bsky.feed.post", "post-1", updated}, {:delete, "app.bsky.feed.post", "post-2"} ], priv, store ) ``` ## 6) Verify Repository Integrity ```elixir :ok = Repository.verify_repo(head2, pub, store) ``` Verification walks commit history and checks: - commit signatures - commit block CIDs - MST node block CIDs - record block CIDs ## 7) Export And Import ```elixir {:ok, car_bytes} = Repository.export_car(head2, store) {:ok, store2} = BlockStore.Memory.start_link() {:ok, imported_head} = Repository.import_car(car_bytes, store2) {:ok, imported_post} = Repository.get_record(imported_head, "app.bsky.feed.post", "post-1", store2) ``` ## 8) Optional Lower-Level Access If you need direct components: - `Potable.MST` for manual tree operations - `Potable.Commit` for explicit commit byte creation/verification - `Potable.CAR` for custom block set archives - `Potable.DagCbor` and `Potable.CID` for codec/addressing primitives