Competitions is StudyMap's second data vertical after places. This issue lands the data layer: a JSON Schema, 50 curated records, and the human-facing contributing guide. Everything else in the competitions label depends on it.
The places dataset is the precedent and we follow it exactly: JSON arrays on disk, a draft-07 schema, a zero-dependency validator in CI, and a static ESM import so the whole dataset bundles at build time.
Files to add
data/competitions/<category>.json - one file per category, mirroring data/places/<type>.json. Root value is a JSON array.
data/competitions.schema.json - modelled directly on data/places.schema.json.
data/competitions/CONTRIBUTING.md - mirroring data/CONTRIBUTING.md.
.github/ISSUE_TEMPLATE/add-competition.yml - mirroring .github/ISSUE_TEMPLATE/add-place.yml.
Record shape
Enums:
category: stem | mathematics | coding | essay_writing | creative_writing | arts_design | film_video | business | finance | humanities | history | debate_mun | research | scholarship | interdisciplinary
format: online | in_person | hybrid
participation: individual | team | individual_or_team
region: international, or an ISO-3166 alpha-2 code
dates[].type: registration_open | registration_close | deadline | round | results | ceremony
country_tracks[].country: one of IN US GB CA AU SG DE FR CN JP KR BR ZA
Carry two conventions over from data/places.schema.json: "format": "date" for every ISO date string, and the verified: { by, on } sub-object with additionalProperties: false.
source_url and timezone are required, not decorative
A countdown timer is a precision claim. It renders a wrong date as confidently as a right one, and a student who misses a scholarship because our clock was stale does not come back. Every date carries the URL it was read from so the next person can recheck it in one click, and valid_till plus the freshness cron is what stops the catalog rotting.
Content sourcing rules
Take facts only: names, organizers, dates, fees, eligibility, age ranges, prizes, official URLs. Facts are not copyrightable.
Write every description fresh. Do not copy prose from doq.world or any other catalog. Their write-ups are their own work, this repo is public, and a lift would be visible in git history forever. One to three sentences, plain, no marketing register.
Do not import anyone else's prestige or selectivity rating. We are not making that editorial call.
The 50 records
All global, with per-country qualifier tracks where a real national pathway exists. Aim for spread across categories rather than 30 essay contests. Marquee names worth including: IMO/IOI national feeders, HMMT, Meta Hacker Cup, Breakthrough Junior Challenge, Foyle Young Poets, Bow Seat Ocean Awareness, Regeneron ISEF, Google Science Fair successors, John Locke, Harvard Crimson Global Essay, Diamond Challenge, Conrad Challenge, NASA Space Apps, F1 in Schools.
country_tracks is where the real value is and it is the part no other catalog has in machine-readable form. Example: an informatics olympiad's entry gets India's ZIO/ZCO/INOI pathway with iarcs.org.in, the US's USACO pathway, the UK's BIO pathway, and so on for whichever of the 13 have a national body.
Acceptance criteria
Competitions is StudyMap's second data vertical after places. This issue lands the data layer: a JSON Schema, 50 curated records, and the human-facing contributing guide. Everything else in the
competitionslabel depends on it.The places dataset is the precedent and we follow it exactly: JSON arrays on disk, a draft-07 schema, a zero-dependency validator in CI, and a static ESM import so the whole dataset bundles at build time.
Files to add
data/competitions/<category>.json- one file per category, mirroringdata/places/<type>.json. Root value is a JSON array.data/competitions.schema.json- modelled directly ondata/places.schema.json.data/competitions/CONTRIBUTING.md- mirroringdata/CONTRIBUTING.md..github/ISSUE_TEMPLATE/add-competition.yml- mirroring.github/ISSUE_TEMPLATE/add-place.yml.Record shape
{ "id": "breakthrough-junior-challenge", "name": "Breakthrough Junior Challenge", "organizer": "Breakthrough Prize Foundation", "organizer_url": "https://breakthroughjuniorchallenge.org", "category": "stem", "subjects": ["physics", "science communication"], "description": "One to three sentences, written by us.", "format": "online", "age_min": 13, "age_max": 18, "participation": "individual", "region": "international", "fee": { "amount": 0, "currency": "USD" }, "prize": "USD 250,000 scholarship plus a lab grant", "official_url": "https://breakthroughjuniorchallenge.org", "cycle_year": 2026, "dates": [ { "label": "Submission deadline", "date": "2026-06-25", "type": "deadline", "timezone": "UTC-4", "estimated": false, "source_url": "https://breakthroughjuniorchallenge.org/rules" } ], "country_tracks": [ { "country": "IN", "official_url": "https://www.iarcs.org.in/", "stages": [ { "name": "ZIO", "date": "2026-11-15", "estimated": false, "source_url": "https://www.iarcs.org.in/" } ] } ], "added_by": "github-username", "verified": { "by": "github-username", "on": "2026-09-05" }, "valid_till": "2027-09-05" }Enums:
category:stem|mathematics|coding|essay_writing|creative_writing|arts_design|film_video|business|finance|humanities|history|debate_mun|research|scholarship|interdisciplinaryformat:online|in_person|hybridparticipation:individual|team|individual_or_teamregion:international, or an ISO-3166 alpha-2 codedates[].type:registration_open|registration_close|deadline|round|results|ceremonycountry_tracks[].country: one ofIN US GB CA AU SG DE FR CN JP KR BR ZACarry two conventions over from
data/places.schema.json:"format": "date"for every ISO date string, and theverified: { by, on }sub-object withadditionalProperties: false.source_urlandtimezoneare required, not decorativeA countdown timer is a precision claim. It renders a wrong date as confidently as a right one, and a student who misses a scholarship because our clock was stale does not come back. Every date carries the URL it was read from so the next person can recheck it in one click, and
valid_tillplus the freshness cron is what stops the catalog rotting.Content sourcing rules
Take facts only: names, organizers, dates, fees, eligibility, age ranges, prizes, official URLs. Facts are not copyrightable.
Write every
descriptionfresh. Do not copy prose from doq.world or any other catalog. Their write-ups are their own work, this repo is public, and a lift would be visible in git history forever. One to three sentences, plain, no marketing register.Do not import anyone else's prestige or selectivity rating. We are not making that editorial call.
The 50 records
All global, with per-country qualifier tracks where a real national pathway exists. Aim for spread across categories rather than 30 essay contests. Marquee names worth including: IMO/IOI national feeders, HMMT, Meta Hacker Cup, Breakthrough Junior Challenge, Foyle Young Poets, Bow Seat Ocean Awareness, Regeneron ISEF, Google Science Fair successors, John Locke, Harvard Crimson Global Essay, Diamond Challenge, Conrad Challenge, NASA Space Apps, F1 in Schools.
country_tracksis where the real value is and it is the part no other catalog has in machine-readable form. Example: an informatics olympiad's entry gets India's ZIO/ZCO/INOI pathway with iarcs.org.in, the US's USACO pathway, the UK's BIO pathway, and so on for whichever of the 13 have a national body.Acceptance criteria
npm run validate(once #N2 lands)idis globally unique across all category filessource_urlthat resolvesdescriptionis copied from another sitescripts/validate-places.mjs:145-149)country_tracksentrydata/competitions/CONTRIBUTING.mddocuments the id convention, the sourcing rules, and the verification expiry window