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 examples/GitHubTriage
- GitHub triage, in Compose kotlin/samples/github
- Rick and Morty, in SwiftUI examples/RickAndMorty
- Rick and Morty, in Compose kotlin/samples/shared
- UIKit and AppKit controllers examples/Controllers
- The exchange examples/Exchange
- Caton the demo app
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| operation | in | variables | spreads |
|---|---|---|---|
mutation CommentComposerAddComment | IssueScreen.swift | $input: AddCommentInput!, $connections: [ID!]! | none |
query IssueDetailPaginationQuery | IssueScreen.swift | $count: Int, $cursor: String, $id: ID! | IssueDetail_issue |
query IssueListPaginationQuery | RepositoryScreen.swift | $count: Int, $cursor: String, $id: ID! | IssueList_repository IssueRow_issue |
query IssueQuery | IssueScreen.swift | $id: ID! | IssueDetail_issue |
query RefreshRowsQuery | TriageScreen.swift | $ids: [ID!]! | IssueRow_issue PullRequestRow_pullRequest |
query RepositoryQuery | RepositoryScreen.swift | $owner: String!, $name: String! | IssueList_repository IssueRow_issue StarButton_repository |
mutation StarButtonAddStar | RepositoryScreen.swift | $input: AddStarInput! | none |
mutation StarButtonRemoveStar | RepositoryScreen.swift | $input: RemoveStarInput! | none |
query TriageQuery | TriageScreen.swift | none | IssueRow_issue PullRequestRow_pullRequest |
| fragment | on | in | spread by |
|---|---|---|---|
IssueDetail_issue | Issue | IssueScreen.swift | IssueDetailPaginationQuery IssueQuery |
IssueList_repository | Repository | RepositoryScreen.swift | IssueListPaginationQuery RepositoryQuery |
IssueRow_issue | Issue | TriageScreen.swift | IssueListPaginationQuery RefreshRowsQuery RepositoryQuery TriageQuery |
PullRequestRow_pullRequest | PullRequest | TriageScreen.swift | RefreshRowsQuery TriageQuery |
StarButton_repository | Repository | RepositoryScreen.swift | RepositoryQuery |
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| operation | in | variables | spreads |
|---|---|---|---|
mutation CommentComposerAddComment | IssueScreen.kt | $input: AddCommentInput!, $connections: [ID!]! | none |
query IssueDetailPaginationQuery | IssueScreen.kt | $count: Int, $cursor: String, $id: ID! | IssueDetail_issue |
query IssueListPaginationQuery | RepositoryScreen.kt | $count: Int, $cursor: String, $id: ID! | IssueList_repository IssueRow_issue |
query IssueQuery | IssueScreen.kt | $id: ID! | IssueDetail_issue |
query RefreshRowsQuery | TriageScreen.kt | $ids: [ID!]! | IssueRow_issue PullRequestRow_pullRequest |
query RepositoryQuery | RepositoryScreen.kt | $owner: String!, $name: String! | IssueList_repository IssueRow_issue StarButton_repository |
mutation StarButtonAddStar | RepositoryScreen.kt | $input: AddStarInput! | none |
mutation StarButtonRemoveStar | RepositoryScreen.kt | $input: RemoveStarInput! | none |
query TriageQuery | TriageScreen.kt | none | IssueRow_issue PullRequestRow_pullRequest |
query ViewerQuery | IssueScreen.kt | none | none |
| fragment | on | in | spread by |
|---|---|---|---|
IssueDetail_issue | Issue | IssueScreen.kt | IssueDetailPaginationQuery IssueQuery |
IssueList_repository | Repository | RepositoryScreen.kt | IssueListPaginationQuery RepositoryQuery |
IssueRow_issue | Issue | RepositoryScreen.kt | IssueListPaginationQuery RefreshRowsQuery RepositoryQuery TriageQuery |
PullRequestRow_pullRequest | PullRequest | TriageScreen.kt | RefreshRowsQuery TriageQuery |
StarButton_repository | Repository | RepositoryScreen.kt | RepositoryQuery |
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| operation | in | variables | spreads |
|---|---|---|---|
query CharacterEpisodesQuery | CharacterScreen.swift | $id: ID! | none |
query CharacterHeaderQuery | CharacterScreen.swift | $id: ID! | CharacterHeader_character |
query CharactersScreenQuery | CharactersScreen.swift | $page: Int | CharacterHeader_character CharacterRow_character |
query EpisodeQuery | EpisodeAndLocationScreens.swift | $id: ID! | CharacterHeader_character CharacterRow_character |
query LocationQuery | EpisodeAndLocationScreens.swift | $id: ID! | CharacterHeader_character CharacterRow_character |
| fragment | on | in | spread by |
|---|---|---|---|
CharacterHeader_character | Character | CharacterScreen.swift | CharacterHeaderQuery CharactersScreenQuery EpisodeQuery LocationQuery |
CharacterRow_character | Character | CharactersScreen.swift | CharactersScreenQuery EpisodeQuery LocationQuery |
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| operation | in | variables | spreads |
|---|---|---|---|
query CharacterEpisodesQuery | CharacterScreen.kt | $id: ID! | none |
query CharacterHeaderQuery | CharacterScreen.kt | $id: ID! | CharacterHeader_character |
query CharactersScreenQuery | CharactersScreen.kt | $page: Int | CharacterHeader_character CharacterRow_character |
query EpisodeQuery | EpisodeAndLocationScreens.kt | $id: ID! | CharacterHeader_character CharacterRow_character |
query LocationQuery | EpisodeAndLocationScreens.kt | $id: ID! | CharacterHeader_character CharacterRow_character |
| fragment | on | in | spread by |
|---|---|---|---|
CharacterHeader_character | Character | CharacterScreen.kt | CharacterHeaderQuery CharactersScreenQuery EpisodeQuery LocationQuery |
CharacterRow_character | Character | CharactersScreen.kt | CharactersScreenQuery EpisodeQuery LocationQuery |
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| operation | in | variables | spreads |
|---|---|---|---|
query CharacterQuery | Characters.graphql | $id: ID! | none |
query CharactersQuery | Characters.graphql | $page: Int | CharacterCell_character |
| fragment | on | in | spread by |
|---|---|---|---|
CharacterCell_character | Character | Characters.graphql | CharactersQuery |
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.
Baton