Baton

Examples

The gallery

Every sample in the repository, Swift and Kotlin, with what the compiler found in it: the GitHub triage apps, Rick and Morty, UIKit and AppKit controllers, the exchange, and Caton.

Every sample is compiled in the repository's checks, and what each plate below lists was found by the compiler when this page was built: the operations each sample sends and the fragments its views declare. The sources are linked; read one screen whole before writing one.

GitHub triage, in SwiftUI#

What the viewer has to look at: open issues and pull requests assigned to or created by them, a repository with a star toggle, and an issue with its comments and reactions. Reads, writes with optimistic responses, interfaces and a union, a connection a mutation appends to, @required and @catch, and a lookup by id, against a schema of about 1,800 definitions. The README's screen is this app's.

GITHUB_TOKEN=$(gh auth token) swift run GitHubTriage
operationinvariablesspreads
mutation CommentComposerAddCommentIssueScreen.swift$input: AddCommentInput!, $connections: [ID!]!none
query IssueDetailPaginationQueryIssueScreen.swift$count: Int, $cursor: String, $id: ID!IssueDetail_issue
query IssueListPaginationQueryRepositoryScreen.swift$count: Int, $cursor: String, $id: ID!IssueList_repository IssueRow_issue
query IssueQueryIssueScreen.swift$id: ID!IssueDetail_issue
query RefreshRowsQueryTriageScreen.swift$ids: [ID!]!IssueRow_issue PullRequestRow_pullRequest
query RepositoryQueryRepositoryScreen.swift$owner: String!, $name: String!IssueList_repository IssueRow_issue StarButton_repository
mutation StarButtonAddStarRepositoryScreen.swift$input: AddStarInput!none
mutation StarButtonRemoveStarRepositoryScreen.swift$input: RemoveStarInput!none
query TriageQueryTriageScreen.swiftnoneIssueRow_issue PullRequestRow_pullRequest
fragmentoninspread by
IssueDetail_issueIssueIssueScreen.swiftIssueDetailPaginationQuery IssueQuery
IssueList_repositoryRepositoryRepositoryScreen.swiftIssueListPaginationQuery RepositoryQuery
IssueRow_issueIssueTriageScreen.swiftIssueListPaginationQuery RefreshRowsQuery RepositoryQuery TriageQuery
PullRequestRow_pullRequestPullRequestTriageScreen.swiftRefreshRowsQuery TriageQuery
StarButton_repositoryRepositoryRepositoryScreen.swiftRepositoryQuery
Plate 1. What the compiler found in examples/GitHubTriage when this page was built: 9 operations and 5 fragments, against the schema its baton.json names.

GitHub triage, in Compose#

The same screens over GitHub's API, as a Compose for Desktop app: the same documents, the same lenses and the same phase, in Kotlin's words. It sends through the Kotlin exchange and keeps an image in the user's cache directory, so a relaunch renders before the network answers.

GITHUB_TOKEN=$(gh auth token) gradle :samples:github:run
operationinvariablesspreads
mutation CommentComposerAddCommentIssueScreen.kt$input: AddCommentInput!, $connections: [ID!]!none
query IssueDetailPaginationQueryIssueScreen.kt$count: Int, $cursor: String, $id: ID!IssueDetail_issue
query IssueListPaginationQueryRepositoryScreen.kt$count: Int, $cursor: String, $id: ID!IssueList_repository IssueRow_issue
query IssueQueryIssueScreen.kt$id: ID!IssueDetail_issue
query RefreshRowsQueryTriageScreen.kt$ids: [ID!]!IssueRow_issue PullRequestRow_pullRequest
query RepositoryQueryRepositoryScreen.kt$owner: String!, $name: String!IssueList_repository IssueRow_issue StarButton_repository
mutation StarButtonAddStarRepositoryScreen.kt$input: AddStarInput!none
mutation StarButtonRemoveStarRepositoryScreen.kt$input: RemoveStarInput!none
query TriageQueryTriageScreen.ktnoneIssueRow_issue PullRequestRow_pullRequest
query ViewerQueryIssueScreen.ktnonenone
fragmentoninspread by
IssueDetail_issueIssueIssueScreen.ktIssueDetailPaginationQuery IssueQuery
IssueList_repositoryRepositoryRepositoryScreen.ktIssueListPaginationQuery RepositoryQuery
IssueRow_issueIssueRepositoryScreen.ktIssueListPaginationQuery RefreshRowsQuery RepositoryQuery TriageQuery
PullRequestRow_pullRequestPullRequestTriageScreen.ktRefreshRowsQuery TriageQuery
StarButton_repositoryRepositoryRepositoryScreen.ktRepositoryQuery
Plate 2. What the compiler found in kotlin/samples/github when this page was built: 10 operations and 5 fragments, against the schema its baton.json names.

Rick and Morty, in SwiftUI#

The public Rick and Morty API through Baton: characters, their details, episodes and locations share one store, so a character seen in a list, in an episode's cast and among a location's residents is one record. The store keeps an image on disk: quit and launch again, and the screens seen before are drawn from it before the network answers. The schema is small enough to read whole, which is why this site's GraphQL chapter uses it.

swift run RickAndMorty
operationinvariablesspreads
query CharacterEpisodesQueryCharacterScreen.swift$id: ID!none
query CharacterHeaderQueryCharacterScreen.swift$id: ID!CharacterHeader_character
query CharactersScreenQueryCharactersScreen.swift$page: IntCharacterHeader_character CharacterRow_character
query EpisodeQueryEpisodeAndLocationScreens.swift$id: ID!CharacterHeader_character CharacterRow_character
query LocationQueryEpisodeAndLocationScreens.swift$id: ID!CharacterHeader_character CharacterRow_character
fragmentoninspread by
CharacterHeader_characterCharacterCharacterScreen.swiftCharacterHeaderQuery CharactersScreenQuery EpisodeQuery LocationQuery
CharacterRow_characterCharacterCharactersScreen.swiftCharactersScreenQuery EpisodeQuery LocationQuery
Plate 3. What the compiler found in examples/RickAndMorty when this page was built: 5 operations and 2 fragments, against the schema its baton.json names.

Rick and Morty, in Compose#

The same screens as Compose Multiplatform, shared by a Compose for Desktop app (kotlin/samples/desktop, with an inspector pane over the store) and an Android app (kotlin/samples/android, which tells the environment the process's lifecycle). The Android app has an Apollo Kotlin twin, kotlin/samples/apollo-android, the same two screens over Apollo Kotlin, for a head-to-head over the same launch.

gradle :samples:desktop:run
operationinvariablesspreads
query CharacterEpisodesQueryCharacterScreen.kt$id: ID!none
query CharacterHeaderQueryCharacterScreen.kt$id: ID!CharacterHeader_character
query CharactersScreenQueryCharactersScreen.kt$page: IntCharacterHeader_character CharacterRow_character
query EpisodeQueryEpisodeAndLocationScreens.kt$id: ID!CharacterHeader_character CharacterRow_character
query LocationQueryEpisodeAndLocationScreens.kt$id: ID!CharacterHeader_character CharacterRow_character
fragmentoninspread by
CharacterHeader_characterCharacterCharacterScreen.ktCharacterHeaderQuery CharactersScreenQuery EpisodeQuery LocationQuery
CharacterRow_characterCharacterCharactersScreen.ktCharactersScreenQuery EpisodeQuery LocationQuery
Plate 4. What the compiler found in kotlin/samples/shared when this page was built: 5 operations and 2 fragments, against the schema its baton.json names.

UIKit and AppKit controllers#

A UIViewController and an NSViewController holding the same handle a view does: the operations live in a .graphql file, the controller asks the environment for the handle, holds the retention, renders what it reads, and renders again when that changes. The recipe is UIKit and AppKit.

swift build --target Controllers
operationinvariablesspreads
query CharacterQueryCharacters.graphql$id: ID!none
query CharactersQueryCharacters.graphql$page: IntCharacterCell_character
fragmentoninspread by
CharacterCell_characterCharacterCharacters.graphqlCharactersQuery
Plate 5. What the compiler found in examples/Controllers when this page was built: 2 operations and 1 fragments, against the schema its baton.json names.

The exchange#

The few dozen lines a production endpoint needs and the library does not ship: a transport that wraps a transport, with one replay of a challenge, a bounded retry with backoff, a deadline across every attempt, and the rule that a mutation is never sent twice. The Kotlin twin is kotlin/samples/exchange. The recipe is the exchange.

Caton#

Caton is the demo app: a macOS menu bar inbox for GitHub notifications, built to show this framework in a real product. It joins each notification to the live state of its pull request or issue, and the number in the menu bar is the number of things waiting on you.