Problem
src/lib/jsonld.ts's schemaOrgCompetitionType() correctly types scholarship-category competitions as EducationalOccupationalProgram instead of Event (a scholarship judged on a body of work isn't a dated event):
export function schemaOrgCompetitionType(category: Competition["category"]): string {
return category === "scholarship" ? "EducationalOccupationalProgram" : "Event";
}
But competitionJsonLd() unconditionally sets eventAttendanceMode on every competition regardless of its resolved @type:
const node: Record<string, unknown> = {
"@context": "https://schema.org",
"@type": schemaOrgCompetitionType(competition.category),
// ...
eventAttendanceMode: EVENT_ATTENDANCE_MODES[competition.format],
isAccessibleForFree: competition.fee.amount === 0,
};
eventAttendanceMode is a schema.org Event-only property — it isn't a valid property of EducationalOccupationalProgram. So the JSON-LD emitted for the 5 records in data/competitions/scholarship.json (e.g. davidson-fellows-scholarship) declares "@type": "EducationalOccupationalProgram" while also carrying an Event-only field, which is exactly the kind of type/property mismatch Google's Rich Results structured-data validator flags.
Fix
In competitionJsonLd(), only include eventAttendanceMode (and startDate/endDate, which are also Event-shaped) when schemaOrgCompetitionType(competition.category) === "Event". For the scholarship branch, consider adding EducationalOccupationalProgram-appropriate properties instead (e.g. applicationDeadline from the record's dates[]) if useful, or simply omit the Event-only fields.
Acceptance criteria
Problem
src/lib/jsonld.ts'sschemaOrgCompetitionType()correctly typesscholarship-category competitions asEducationalOccupationalPrograminstead ofEvent(a scholarship judged on a body of work isn't a dated event):But
competitionJsonLd()unconditionally setseventAttendanceModeon every competition regardless of its resolved@type:eventAttendanceModeis a schema.orgEvent-only property — it isn't a valid property ofEducationalOccupationalProgram. So the JSON-LD emitted for the 5 records indata/competitions/scholarship.json(e.g.davidson-fellows-scholarship) declares"@type": "EducationalOccupationalProgram"while also carrying anEvent-only field, which is exactly the kind of type/property mismatch Google's Rich Results structured-data validator flags.Fix
In
competitionJsonLd(), only includeeventAttendanceMode(andstartDate/endDate, which are alsoEvent-shaped) whenschemaOrgCompetitionType(competition.category) === "Event". For thescholarshipbranch, consider addingEducationalOccupationalProgram-appropriate properties instead (e.g.applicationDeadlinefrom the record'sdates[]) if useful, or simply omit the Event-only fields.Acceptance criteria
eventAttendanceMode(andstartDate/endDate) only appear onEvent-typed JSON-LD nodessrc/lib/jsonld.test.ts(or a new test) covers a scholarship-category competition