diff --git a/Sources/ContactListFeature/ContactListTableController.swift b/Sources/ContactListFeature/ContactListTableController.swift
index 8215991d49982bf7f3780636947fcd7adf575adb..adc9da1a16c369715abd09f35f5f9c9f3380704e 100644
--- a/Sources/ContactListFeature/ContactListTableController.swift
+++ b/Sources/ContactListFeature/ContactListTableController.swift
@@ -5,78 +5,107 @@ import XXModels
 import AppResources
 
 final class ContactListTableController: UITableViewController {
-  private var collation = UILocalizedIndexedCollation.current()
-  private var sections: [[Contact]] = [] {
-    didSet { self.tableView.reloadData() }
+  private final class Row: NSObject {
+    init(contact: XXModels.Contact) {
+      self.contact = contact
+      self.title = contact.nickname ?? contact.username ?? ""
+    }
+
+    let contact: XXModels.Contact
+    @objc let title: String
+  }
+
+  private struct Section {
+    var title: String
+    var rows: [Row]
   }
-  
+
+  private var collation = UILocalizedIndexedCollation.current()
+  private var sections: [Section] = []
+
   private let viewModel: ContactListViewModel
   private var cancellables = Set<AnyCancellable>()
   private let tapRelay = PassthroughSubject<Contact, Never>()
-  
+
   var didTap: AnyPublisher<Contact, Never> { tapRelay.eraseToAnyPublisher() }
-  
+
   override func viewDidLoad() {
     super.viewDidLoad()
     setupTableView()
   }
-  
+
   init(_ viewModel: ContactListViewModel) {
     self.viewModel = viewModel
     super.init(style: .grouped)
   }
-  
+
   required init?(coder: NSCoder) { nil }
-  
+
   private func setupTableView() {
     tableView.separatorStyle = .none
     tableView.register(AvatarCell.self)
     tableView.backgroundColor = Asset.neutralWhite.color
     tableView.sectionIndexColor = Asset.neutralDark.color
     tableView.contentInset = UIEdgeInsets(top: -20, left: 0, bottom: 0, right: 0)
-    
+
     viewModel.contacts
       .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in
-        let results = IndexedListCollator().sectioned(items: $0)
-        self.collation = results.collation
-        self.sections = results.sections
+      .sink { [unowned self] contacts in
+        sections = makeSections(from: contacts)
+        tableView.reloadData()
       }.store(in: &cancellables)
   }
-  
+
+  private func makeSections(from contacts: [XXModels.Contact]) -> [Section] {
+    let rows = contacts.map(Row.init(contact:))
+    let selector: Selector = #selector(getter: Row.title)
+    let sortedRows = collation.sortedArray(from: rows, collationStringSelector: selector) as! [Row]
+    var sections = collation.sectionTitles.map { Section(title: $0, rows: []) }
+    sortedRows.forEach { row in
+      let sectionNumber = collation.section(for: row, collationStringSelector: selector)
+      sections[sectionNumber].rows.append(row)
+    }
+    sections.removeAll(where: \.rows.isEmpty)
+    return sections
+  }
+
   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     let cell: AvatarCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
-    let contact = sections[indexPath.section][indexPath.row]
+    let contact = sections[indexPath.section].rows[indexPath.row].contact
     let name = (contact.nickname ?? contact.username) ?? "Fetching username..."
-    
     cell.setup(title: name, image: contact.photo)
     return cell
   }
-  
+
   override func numberOfSections(in: UITableView) -> Int {
     sections.count
   }
-  
+
   override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
-    sections[section].count
+    sections[section].rows.count
   }
-  
+
   override func tableView(_: UITableView, didSelectRowAt indexPath: IndexPath) {
-    tapRelay.send(sections[indexPath.section][indexPath.row])
+    let contact = sections[indexPath.section].rows[indexPath.row].contact
+    tapRelay.send(contact)
   }
-  
+
   override func sectionIndexTitles(for: UITableView) -> [String]? {
     collation.sectionIndexTitles
   }
-  
+
   override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
-    collation.sectionTitles[section]
+    sections[section].title
   }
-  
+
   override func tableView(_: UITableView, sectionForSectionIndexTitle: String, at index: Int) -> Int {
-    collation.section(forSectionIndexTitle: index)
+    if let index = sections.lastIndex(where: { $0.title <= sectionForSectionIndexTitle }) {
+      return index
+    } else {
+      return sections.index(before: sections.endIndex)
+    }
   }
-  
+
   override func tableView(_: UITableView, heightForRowAt: IndexPath) -> CGFloat {
     64
   }