Use when the user asks to "add a GraphQL query", "add a mutation", "add a subscription", "add API logic for X", "wire up X to the backend", "add a new operation for X", or "fetch X from the API" in the Galaxy Voyagers Flutter app.
This app uses graphql_codegen + build_runner to generate fully-typed Dart code from .graphql files. You never write API client code by hand — you write a .graphql document and run codegen.
The schema is the contract. Do NOT look at backend server code.
Schema location: services/mobile/lib/graphql/schema.graphql
Read it to find:
CreateCharacterInput) and their required/optional fields.graphql FileOperations for an entity live together:
services/mobile/lib/graphql/
[domain]/
[entity].graphql ← human-written operations (edit this)
[entity].graphql.dart ← generated, do not edit
Examples:
graphql/character/character.graphqlgraphql/location/location.graphqlIf the domain directory doesn't exist yet, create it.
Follow the app's established patterns exactly.
Fragment pattern (define once, reuse everywhere):
fragment AllShip on Ship {
id
title
text
createdAt
user
images {
fileName
URL
x
y
id
}
}
Query:
query ships {
ships(input: {}) {
...AllShip
}
}
query ship($id: Int!) {
ship(input: { id: $id }) {
...AllShip
}
posts(input: { id: $id, class: "ships" }) {
...PostStandard
}
}
Mutation:
mutation createShip(
$title: String!
$text: String
$files: [FileInput]
) {
createShip(
input: { title: $title, text: $text, files: $files }
) {
...AllShip
}
}
Subscription (AI streaming):
subscription ragStreamShip(
$title: String!
$text: String
) {
ragStreamShip(input: { title: $title, text: $text }) {
text
done
}
}
cd services/mobile && dart run build_runner build --delete-conflicting-outputs
Codegen produces these in [entity].graphql.dart:
| Generated symbol | How to use |
|---|---|
Variables$Query$ships | Typed query variables |
Query$ships$Widget | Builder widget for queries |
useMutation$createShip() | Hook for mutations |
Variables$Mutation$createShip | Typed mutation variables |
client.subscribe$ragStreamShip(...) | Stream for subscriptions |
Query widget (in a page):
import '../../graphql/ship/ship.graphql.dart';
Query$ships$Widget(
options: Options$Query$ships(
pollInterval: const Duration(seconds: 10),
),
builder: (result, {fetchMore, refetch}) {
if (result.isLoading) return const Center(child: CircularProgressIndicator());
if (result.hasException) return Center(child: Text('Error: ${result.exception}'));
final ships = result.parsedData?.ships ?? [];
// build UI from ships
},
)
Mutation hook (in a form):
final mutation = useMutation$createShip();
final result = await mutation
.runMutation(Variables$Mutation$createShip(title: 'My Ship'))
.networkResult;
if (result?.hasException ?? true) {
// show error snackbar
} else {
context.go('/ships');
}
.graphql file..graphql.dart files.