Blocked by #198.
50 competition detail pages are 50 new indexable URLs, and this is the kind of content people search for by name. Give them proper metadata.
Files
src/app/sitemap.ts - add competition routes
src/app/competitions/[slug]/opengraph-image.tsx - new
src/lib/jsonld.ts - extend, it already exists and is tested
src/app/competitions/[slug]/page.tsx - wire up generateMetadata
Sitemap
src/app/sitemap.ts already maps over places (:14) and docsNav (:20). Add /competitions and every /competitions/<id>.
Use a real lastModified from verified.on or the most recently changed date in the record. Do not use new Date(). That is precisely the bug open issue #163 exists for on the places side, so do not reproduce it here.
OG images
src/app/city/[slug]/opengraph-image.tsx is the working precedent, including :150-169 where it renders category counts into the image. @vercel/og 1.0.1 is already a dependency.
Per competition: name, organizer, category, next deadline. Keep it legible at thumbnail size, which means a short name and large type rather than the full metadata table.
JSON-LD
src/lib/jsonld.ts exists and has tests at src/lib/jsonld.test.ts. Follow that structure.
Competitions map cleanly onto schema.org Event or, for scholarships, EducationalOccupationalProgram. Include name, description, startDate and endDate from dates[], organizer, url, eventAttendanceMode from format, and isAccessibleForFree from fee.
Only emit dates that are estimated: false. Publishing an estimated date as structured data invites search engines to present a guess as a fact.
Acceptance criteria
Blocked by #198.
50 competition detail pages are 50 new indexable URLs, and this is the kind of content people search for by name. Give them proper metadata.
Files
src/app/sitemap.ts- add competition routessrc/app/competitions/[slug]/opengraph-image.tsx- newsrc/lib/jsonld.ts- extend, it already exists and is testedsrc/app/competitions/[slug]/page.tsx- wire upgenerateMetadataSitemap
src/app/sitemap.tsalready maps over places (:14) anddocsNav(:20). Add/competitionsand every/competitions/<id>.Use a real
lastModifiedfromverified.onor the most recently changed date in the record. Do not usenew Date(). That is precisely the bug open issue #163 exists for on the places side, so do not reproduce it here.OG images
src/app/city/[slug]/opengraph-image.tsxis the working precedent, including:150-169where it renders category counts into the image.@vercel/og1.0.1 is already a dependency.Per competition: name, organizer, category, next deadline. Keep it legible at thumbnail size, which means a short name and large type rather than the full metadata table.
JSON-LD
src/lib/jsonld.tsexists and has tests atsrc/lib/jsonld.test.ts. Follow that structure.Competitions map cleanly onto schema.org
Eventor, for scholarships,EducationalOccupationalProgram. Include name, description,startDateandendDatefromdates[],organizer,url,eventAttendanceModefromformat, andisAccessibleForFreefromfee.Only emit dates that are
estimated: false. Publishing an estimated date as structured data invites search engines to present a guess as a fact.Acceptance criteria
lastModifiedvaluessrc/lib/jsonld.test.ts