This document summarizes the ATProto Lexicon Style Guide rules that are checked by our automated checker. For the complete guide, visit: https://atproto.com/guides/lexicon-style-guide
- Format: Reverse-DNS notation (e.g.,
org.hypercerts.claim.activity) - Case: All lowercase
- Segments: Use descriptive, concise names
- Avoid: Numbers in authority segments, generic names like "item" or "thing"
- Recommendation: Use
anyfor most record keys to allow flexible client-side naming - TIDs: When using TIDs (Timestamp IDs), ensure they're appropriate for the use case
- Literal keys: Only use for singleton records or very specific use cases
- Format: camelCase
- Clarity: Use clear, descriptive names
- Avoid: Abbreviations unless widely understood
- Consistency: Use consistent terminology across related lexicons
- Completeness: Every lexicon should have a clear description
- Detail: Explain the purpose and usage
- Context: Provide enough information for developers to understand
- Required: All properties should have descriptions
- Clarity: Explain what the property represents and how it should be used
- Format hints: Include format expectations when relevant
- Coverage: All definitions (objects, arrays, etc.) should have descriptions
- Purpose: Explain the role of the definition in the schema
- Primitives: Use appropriate primitive types (string, integer, boolean)
- Formats: Apply format constraints (datetime, uri, cid, did, etc.)
- Refs: Use refs for reusable types and relationships
- Unions: Use unions when a property can be one of several types. All variants in a union must be object or record types (strings/numbers are not allowed directly in unions by ATProto spec).
- String lengths: Always set maxLength for strings (except format-typed fields like
datetime,uri,at-uri,did) - maxGraphemes: Consider using maxGraphemes for user-visible text
- Array constraints: Consider maxLength for arrays
- Required fields: Mark truly required fields, keep optional what can be optional
- Size limits: Always specify maxSize for blobs
- MIME types: Specify accepted MIME types with the
acceptproperty - Documentation: Document blob size limits and types clearly
- Usage: Use
com.atproto.repo.strongReffor references to other records - Documentation: Clearly document what type of record is expected
- Validation: Specify the expected lexicon type in the description
- Consistency: Use consistent patterns for arrays of references
- Documentation: Explain the relationship and cardinality
- Format: Always use
format: "datetime"for timestamp fields - Naming: Use clear names like
createdAt,updatedAt,publishedAt - Requirement: Mark as required when appropriate
- Documentation: Explain when the timestamp should be set
- Standard: Include a
createdAtfield for records - Type:
stringwithformat: "datetime" - Description: "Client-declared timestamp when this record was originally created"
- Usage: Include
updatedAtfor mutable records - Type:
stringwithformat: "datetime" - Description: "Client-declared timestamp when this record was last updated"
- Consideration: Think about versioning strategy for evolving schemas
- Migration: Document breaking changes
- maxLength: Always set for strings without a
format,enum, orknownValues(prevents abuse) - maxGraphemes: Use for user-facing text (better UX for internationalization)
- Patterns: Use regex patterns when format validation is needed
- Range: Consider minimum and maximum values
- Integers: Use integer type when fractional values don't make sense
- Conservative: Only mark as required if truly necessary
- Flexibility: Allow optional fields for future extensibility
- Documentation: Explain when optional fields should be used
- Comprehensive: Document all types, properties, and constraints
- Examples: Include example values in descriptions when helpful
- Context: Explain relationships and dependencies
- README: Maintain high-level documentation
- Migration guides: Document schema changes and migrations
- Examples: Provide usage examples
- Grouping: Group related lexicons in namespaces
- Definitions: Use
defs.jsonfor shared definitions - Modularity: Keep lexicons focused and modular
- Explicit: Clearly document dependencies on other lexicons
- Minimal: Minimize cross-lexicon dependencies
- Standard: Use standard ATProto lexicons when appropriate
- PII: Be careful with personally identifiable information
- Access control: Consider who can read/write records
- Validation: Validate all input data
- DoS prevention: Set appropriate size limits on all fields
- Blob limits: Be conservative with blob size limits
- Array limits: Limit array sizes to prevent abuse
The style:check script checks for:
- ✅ All lexicons have descriptions
- ✅ All properties have descriptions
- ✅ All definitions have descriptions
- ✅ String properties have maxLength constraints (skipped for format/enum/knownValues fields)
- ✅ Blob properties have maxSize and accept properties
- ✅ DateTime fields use the correct format
- ✅ Property names use camelCase
- ✅ Required fields are properly marked
- ✅ StrongRef usage is documented
- ✅ Lexicon IDs follow naming conventions
- ✅ Union types only contain object or record types (no primitives)
npm run style:checkThis will check all lexicons in the lexicons/ directory and report any style guide violations.