Prototype to contract
Replace prototype data and action seams with fragments, route queries, and backend contract SDL.
Read
- Read the current schema,
schemaExtensions, GraphQL Client config, route entry, prototype data, and local action hooks.
- Follow the app's existing graphql loading and generated-artifact conventions.
- Use graphql-schema-design skill for schema names, nullability, connections, mutation payloads, and typed errors.
Components
- Preserve prototype boundaries unless the component reads fields from more than one entity.
- Give each data-bound component one primary entity and one colocated fragment for the subset it reads.
- use the graphql clients equivalent of
useFragment and use data masking!
- Pass related entities to child components as fragment data; do not read their fields in the parent.
- Split shells from data-bound content when the shell would otherwise own multiple entity fragments.
- Keep local UI state, formatting, icons, labels, and styling out of GraphQL.
Reads
- Replace each rendered mock field with a schema field or schema extension field.
- Do not carry unused mock fields into GraphQL.
- Treat computed product facts as schema fields when the backend owns the truth.
- Keep pure presentation derivations in the client.
- Use connections for lists that can grow beyond a bounded UI fixture; put counts on the connection.
- Put relationship-specific data on the connection edge, such as
joinedAt on UserGroupEdge.
- Use edge fields only for facts about that parent-to-node relationship.
- If the UI renders the relationship as the primary object, model it as its own node and connection, such as
UserGroupMembershipConnection, instead of overloading UserGroupConnection.
- Follow the naming rules of the project.
Actions
- Start from the prototype's local mutation-shaped hooks.
- If the mutation exists in the schema, replace the hook implementation with Relay while keeping its call shape.
- Add a schema mutation for every user action in the requested workflow.
Contract
- Put new fields, types, subscriptions, and mutations directly into the schema file.
- Docstring every added schema element (fields, types, mutations, etc.) with a precise use case description, product meaning, domain knowledge, and null/error semantics.
- Give each mutation unique
Input and Payload types.
- Return a nullable changed entity plus
errors: [<Mutation>Error!]!.
- Define the shared
Error interface, a per-mutation error union, and concrete error types with useful fields.
Example
function ReviewCard({ review }: { $ref: ReviewCard_review$key }) {
const data = useFragment(
graphql`
fragment ReviewCard_review on Review {
body
author {
...UserChip_user
}
}
`,
$ref,
);
return (
<article>
<p>{data.body}</p>
<UserChip user={data.author} />
</article>
);
}
function ReviewForm() {
const [createReview, { loading, error }] = useCreateReviewMutation();
return (
<button disabled={loading} => createReview({ body: "..." })}>
Post
</button>
);
}
Finish
- Wire the route query to spread the top-level feature fragments.
- Run the repo's Relay compiler and typecheck/build commands.
- Remove prototype mock data and local fake persistence.
- Review the extension file with
/graphql-schema-design review.
1---2name: prototype-to-contract3description: Convert a local-only prototype into Relay-backed component fragments and a schemaExtensions backend contract. Use when mock data and local action hooks must become route queries, colocated fragments, and read/write GraphQL specs. Trigger on "prototype to contract", "mock to contract", "turn this prototype into a contract", "fragmentize this page", "wire this mocked page to GraphQL", or "spec this feature for the backend". Do not use for isolated fragment cleanup or schema design without a prototype UI.4---56# Prototype to contract78Replace prototype data and action seams with fragments, route queries, and backend contract SDL.910## Read1112- Read the current schema, `schemaExtensions`, GraphQL Client config, route entry, prototype data, and local action hooks.13- Follow the app's existing graphql loading and generated-artifact conventions.14- Use graphql-schema-design skill for schema names, nullability, connections, mutation payloads, and typed errors.1516## Components1718- Preserve prototype boundaries unless the component reads fields from more than one entity.19- Give each data-bound component one primary entity and one colocated fragment for the subset it reads.20 - use the graphql clients equivalent of `useFragment` and use data masking!21- Pass related entities to child components as fragment data; do not read their fields in the parent.22- Split shells from data-bound content when the shell would otherwise own multiple entity fragments.23- Keep local UI state, formatting, icons, labels, and styling out of GraphQL.2425## Reads2627- Replace each rendered mock field with a schema field or schema extension field.28- Do not carry unused mock fields into GraphQL.29- Treat computed product facts as schema fields when the backend owns the truth.30- Keep pure presentation derivations in the client.31- Use connections for lists that can grow beyond a bounded UI fixture; put counts on the connection.32 - Put relationship-specific data on the connection edge, such as `joinedAt` on `UserGroupEdge`.33 - Use edge fields only for facts about that parent-to-node relationship.34 - If the UI renders the relationship as the primary object, model it as its own node and connection, such as `UserGroupMembershipConnection`, instead of overloading `UserGroupConnection`.35- Follow the naming rules of the project.3637## Actions3839- Start from the prototype's local mutation-shaped hooks.40- If the mutation exists in the schema, replace the hook implementation with Relay while keeping its call shape.41- Add a schema mutation for every user action in the requested workflow.4243## Contract4445- Put new fields, types, subscriptions, and mutations directly into the schema file.46- Docstring every added schema element (fields, types, mutations, etc.) with a precise use case description, product meaning, domain knowledge, and null/error semantics.47- Give each mutation unique `Input` and `Payload` types.48- Return a nullable changed entity plus `errors: [<Mutation>Error!]!`.49- Define the shared `Error` interface, a per-mutation error union, and concrete error types with useful fields.5051## Example5253```tsx54function ReviewCard({ review }: { $ref: ReviewCard_review$key }) {55 const data = useFragment(56 graphql`57 fragment ReviewCard_review on Review {58 body59 author {60 ...UserChip_user61 }62 }63 `,64 $ref,65 );6667 return (68 <article>69 <p>{data.body}</p>70 <UserChip user={data.author} />71 </article>72 );73}74```7576```tsx77function ReviewForm() {78 const [createReview, { loading, error }] = useCreateReviewMutation();79 return (80 <button disabled={loading} onClick={() => createReview({ body: "..." })}>81 Post82 </button>83 );84}85```8687## Finish8889- Wire the route query to spread the top-level feature fragments.90- Run the repo's Relay compiler and typecheck/build commands.91- Remove prototype mock data and local fake persistence.92- Review the extension file with `/graphql-schema-design review`.