Lanyards Types Generation#
Lanyards uses the AT Protocol Lexicon CLI @atproto/lex-cli to automatically generate TypeScript types from the lexicon JSON definitions.
Generated Files#
When you run the code generation, the following files are created in src/types/generated/:
src/types/generated/
├── index.ts - Main export file with all types
├── lexicons.ts - Lexicon definitions for runtime validation
├── util.ts - Utility types and helpers
└── types/at/lanyard/ - Generated type definitions
├── researcher.ts - Researcher record types
├── work.ts - Work record types
├── event.ts - Event record types
├── link.ts - Link record types
├── publication.ts - Publication object types
├── organization.ts - Organization object types
└── location.ts - Location object types
NOTE
The types are NOT committed to git in most workflows, but are generated as part of the build process.
Commands#
Generate types once:
npm run lex:gen
This command reads all .json files in the lexicons/ directory and generates TypeScript types in src/types/generated/.
Watch mode (development):
npm run lex:watch
Watches for changes to lexicon files and automatically regenerates types.
Build process:
npm run build
The build command automatically runs lex:gen before building the Next.js app to ensure types are up-to-date.
How It Works#
- Lexicon Definitions: JSON files in
lexicons/define the schema using AT Protocol lexicon syntax - CLI Tool:
@atproto/lex-cliparses the JSON definitions - Type Generation: Creates TypeScript interfaces, types, and validation schemas
- Import & Use: Generated types are imported throughout the codebase via
@/types/generated
Generated Type Structure#
Each generated file includes:
- Record types: For top-level collection records (researcher, work, event, link)
- Object types: For embedded objects (location, organization, publication)
- Input/Output schemas: For API operations (create, update, delete)
- Validation functions: Runtime validation using the lexicon definitions
Example Usage#
import {
Researcher,
Work,
Event,
Link
} from '@/types/generated';
// Use generated types in your code
const researcher: Researcher.Record = {
did: 'did:plc:...',
handle: 'researcher.bsky.social',
createdAt: new Date().toISOString(),
// ... other fields
};
Type Declaration Fixes#
Due to import path resolution in generated types, we maintain custom type declarations in src/types/:
atproto.d.ts: Namespace declarations for AT Protocol repo operationsmultiformats.d.ts: Module declaration for CID imports
These ensure the generated types work correctly with the AT Protocol SDK.
Regenerating Types#
You should regenerate types whenever you:
- Modify lexicon files: Add/remove fields, change types, update descriptions
- Add new lexicons: Create new
.jsonfiles inlexicons/ - Change constraints: Update validation rules (maxLength, enum values, etc.)
- Pull changes: After pulling changes that include lexicon updates