api-conventions
Skill13 starsChanged 10 days agoMITView on GitHub
How this GraphQL schema is named and shaped - camelCase fields, nullability, Relay connections over offset paging with opaque cursors, mutation conventions with typed ValidationError and NotFoundError payload errors, the VALIDATION and NOT_FOUND error codes on queries, depth limits and authorization. Use when naming a field or argument, deciding nullability, returning a list, or changing how errors appear.
15 other projects use a version of this.
Adopted by
Most recently taken up by
- LeanMeanCleanApps/CleanLambdaFunctiontheir own version, first seen Nov 15, 2026
- LeanMeanCleanApps/CleanWebApitheir own version, first seen Nov 15, 2026
- LeanMeanCleanApps/CleanMinimalApitheir own version, first seen Nov 15, 2026
- LeanMeanCleanApps/CleanModelContextProtocoltheir own version, first seen Nov 8, 2026
- willdady/platypustheir own version, first seen Nov 8, 2026
- leroyguillaume/claudetheir own version, first seen Oct 30, 2026
Other versions15 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 15
- mx-space/core★ 567same name
- LeanMeanCleanApps/CleanMinimalApi★ 400same name
- TheDecipherist/claude-code-mastery-project-starter-kit★ 337same name
- willdady/platypus★ 130same name
- maxyeh0817/Forge★ 34same name
- harness-studio/harness-studio★ 9same name
- leroyguillaume/claude★ 7same name
- LeanMeanCleanApps/CleanWebApi★ 4same name
- CodeWithBehnam/cc-docs★ 2same name
- lodetomasi/claude-code-training-lab★ 2same name
5 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository41 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- add-a-use-caseSkill
- branches-and-pull-requestsSkill
- cancellationSkill
- ci-for-your-solutionSkill
- ci-pipelineSkill
- clean-architecture-layersSkill
- configuration-and-environmentsSkill
- coverageSkill
- csharp-house-styleSkill
- data-access-ef-coreSkill
- database-migrationsSkill
- dataloadersSkill
- docker-and-composeSkill
- docs-and-voiceSkill
- errors-and-exceptionsSkill
- expose-a-use-caseSkill
- family-syncSkill
- health-checksSkill
- integration-testsSkill
- mapping-with-mapperlySkill
- mediatorSkill
- nitroSkill
- optional-token-authSkill
- packages-and-dependenciesSkill
- pagingSkill
- presentation-integration-testsSkill
- releasesSkill
- sample-dataSkill
- schema-snapshotSkill
- security-findingsSkill
- serilogSkill
- telemetrySkill
- template-authoringSkill
- test-designSkill
- time-providerSkill
- unit-testsSkill
- validationSkill
- writing-a-skillSkill
- xml-docs-and-openapiSkill
The file
We split this skill into the rules it gives an agent
3 rules. 0 are common, 2 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 11 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 48
Test each error code or error type in the field's integration tests (test-design).
- Distinctive: line 64
Put stack traces or internal detail in an error message or extension.
- Distinctive: line 65
Add a second error filter.
“Common” is measured: kept by at least 6 in 10 of the 11 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
API conventions (GraphQL)
The rule
| Thing | Convention |
| Fields and arguments | camelCase, named for what they return: movie(id), movies(query, first, after) |
| Types | The Application entity's name: Movie, MovieSummary, Review |
| Mutations | Hot Chocolate's mutation conventions: createReview(input: CreateReviewInput!): CreateReviewPayload!, where the payload holds the result (review) and errors |
| Ids | UUID |
| Nullability | Entity fields are non-null. A field that can fail returns a nullable result, so an error nulls only that field |
| Lists | Relay connections (nodes, edges, pageInfo, totalCount), forward only, first defaults to 10 and is at most 50 |
| Depth | Queries deeper than 15 levels are refused (AddMaxExecutionDepthRule(15)) |
| Cost | Hot Chocolate's cost analysis is on, so the schema carries @cost and @listSize and expensive queries are refused |
Connections sit on top of the shared offset paging. PageExtensions in GraphQL/Extensions/ makes each cursor a base64 offset:<n> and turns an after cursor back into an offset. A cursor that didn't come from us is a validation error.
Mutations report the failures a caller can fix as typed errors in the payload, through [Error<T>] on the mutation. Each error type in GraphQL/Errors/ takes the Application exception in its constructor and implements the Error interface, so it has a message:
| Exception | Error type | Fields |
ValidationException | ValidationError | message "One or more validation errors occurred.", and fields, each with field and messages |
NotFoundException | NotFoundError | message, the exception's message |
Queries, and anything a mutation doesn't declare, go through ApplicationErrorFilter in GraphQL/Errors/, which maps Application exceptions onto GraphQL errors:
| Exception | extensions.code | Message and extensions |
ValidationException | VALIDATION | "One or more validation errors occurred.", with extensions.errors grouping messages by property |
NotFoundException | NOT_FOUND | The exception's message |
| Anything else | Hot Chocolate's own | "Unexpected Execution Error", with the exception details hidden unless a debugger is attached |
Hot Chocolate returns an unexpected exception to the client and logs nothing, so the filter logs it as Error, with the exception and the field path (serilog). The filter is built from the schema's services, so ProgramExtensions hands it a logger from the application's with GetRootServiceProvider().
Steps
- Name new fields and arguments after the data, not the Application class (
reviews, notgetReviewsQuery). - Decide nullability on purpose: non-null for fields that always have a value, nullable for a field whose resolver can throw.
- Return a connection for any list that can grow. Never an unbounded list.
- Report a new kind of failure as an Application exception. Add an error type for it in
GraphQL/Errors/and an[Error<T>]on each mutation that can raise it, and a case toApplicationErrorFilterwith its own code for queries, with a unit test intests/Presentation.Tests.Unit/GraphQL/Errors/. - Test each error code or error type in the field's integration tests (
test-design). Ask for errors witherrors{__typename,...on Error{message}}.
Example
// src/Presentation/GraphQL/Errors/ApplicationErrorFilter.cs
NotFoundException notFoundException => ErrorBuilder.FromError(error)
.SetMessage(notFoundException.Message)
.SetCode("NOT_FOUND")
.Build(),Don't
- Expose offset arguments or backward paging.
- Change a field's name, type or nullability without updating the schema snapshot and saying so in the pull request. It breaks clients.
- Put stack traces or internal detail in an error message or extension.
- Add a second error filter.
Check
dotnet test tests/Presentation.Tests.IntegrationDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

