← All craftbooks

GraphQL API

Build: software and codeevalv1.0.1released 2026-07-16workflow: build-loop

Build a GraphQL API with a typed schema (SDL), resolvers, queries, mutations, and input validation. Designs the schema FIRST — types, fields, nullability, query/mutation operations, and the resolver-to-data mapping — because in GraphQL the schema IS the contract, then implements resolvers, then writes operation tests covering each query, mutation, and error. Covers GraphQL schema definition language, resolvers, nullable vs non-null fields, mutations, query arguments, N+1 awareness, and error handling.

Steps

Entry step: schema-design. Each step names the specialist role it wants; the full working prompt is expandable.

  1. Schema designplannerentry

    lock the SDL types, queries, mutations, nullability

    Show working prompt
    Design the GraphQL schema before any resolver code — in GraphQL the schema is the contract. Step 1: Define the object types and their fields in SDL, deciding nullability (`String` vs `String!`) deliberately for each field. Step 2: Define the root `Query` operations (what can be read) and `Mutation` operations (what can be changed), with their argument types and input types. Step 3: For each operation, note which data source/store backs it and what a resolver must return. Step 4: Decide error handling: which conditions return null vs throw a typed GraphQL error, and the shape of user-facing errors. Step 5: Write a numbered acceptance-criteria checklist of 5-9 items (e.g. 'querying user(id) returns the user or null', 'createUser mutation validates input and returns the created node', 'a non-null field never resolves to null', 'invalid input yields a GraphQL error, not a crash'). `write_task_note` the SDL + checklist and write the same to the produces path. No resolvers yet.
  2. Build resolversdeveloper

    implement the schema + resolvers

    Show working prompt
    Implement the GraphQL server in a single runnable source file. Step 1: Declare the schema exactly as designed (SDL string or schema-builder calls) — same types, fields, nullability, operations. Step 2: Write a resolver for every Query and Mutation field; resolvers must honor the declared return types and nullability. Step 3: Validate mutation inputs before mutating; on invalid input throw a typed GraphQL error with a clear message. Step 4: Use an in-memory store if no DB was specified, and make sure non-null fields are always populated. On a loop-back, fix only the named gaps without regressing working resolvers. `write_task_note` the file path and which criteria now pass.
  3. Write operation testsdeveloper

    test each query, mutation, and error

    Show working prompt
    Write tests that execute real GraphQL operations against the schema. Step 1: For each Query, assert the returned shape matches the SDL (including nulls where allowed). Step 2: For each Mutation, assert the happy path returns the created/updated node, then assert invalid input produces a GraphQL error rather than a crash. Step 3: Add a test proving a non-null field never resolves to null. Step 4: Add a create-then-query round-trip to prove state wiring. Make tests runnable and self-contained. `write_task_note` the test file path and pass/fail count.
  4. Evaluatereviewer

    Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.

    Show working prompt
    Run the tests and execute sample operations. For EACH acceptance criterion: confirm queries return the SDL-correct shape and nullability, confirm mutations validate input and return the right node, confirm invalid input yields a typed GraphQL error (not a crash), and confirm non-null fields are never null. Write PASS/FAIL per criterion.
    
    Then route — this is the whole point of the loop:
    
    - **Every criterion PASSES →** call `advance_task_step({ ref, stepId: "evaluate", next: "finish" })`.
    - **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: "evaluate", next: "build" })` to loop back. The builder fixes exactly those gaps.
    
    Never route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.
  5. Finishdeveloper

    All acceptance criteria met. Stamp a short summary and report DONE.

    Show working prompt
    Every acceptance criterion passed. Write a one-paragraph DONE summary to task notes via `write_task_note`: what was built, the deliverable path(s), and a one-line confirmation that each criterion is met. Then report DONE.

Triggers

Phrases that suggest this craftbook to a crew.

Source

View this craftbook on GitHub · MIT license