Competitions live in data/competitions/<category>.json, one file per category, one JSON
object per competition.
This file is the single source of truth for the competition-record schema - README.md,
CONTRIBUTING.md, and ARCHITECTURE.md link here instead of repeating it. The shape
below is also machine-enforced by competitions.schema.json, which
npm run validate checks every record against.
| File | What goes here |
|---|---|
stem.json |
General science, engineering and science-fair competitions |
mathematics.json |
Mathematics olympiads and tournaments |
coding.json |
Competitive programming, cybersecurity and app-building competitions |
essay_writing.json |
Argumentative, analytical and journalistic essay competitions |
creative_writing.json |
Poetry, fiction and other creative writing competitions |
arts_design.json |
Visual art, portfolio and design competitions |
film_video.json |
Film and video competitions |
business.json |
Entrepreneurship, pitch and business case competitions |
finance.json |
Investing, personal finance and economics competitions |
humanities.json |
Language, linguistics and other humanities competitions not covered above |
history.json |
History research and quiz competitions |
debate_mun.json |
Debate, Model UN and other academic tournament competitions |
research.json |
Independent research competitions |
scholarship.json |
Scholarship programs judged on a body of work rather than a single entry |
interdisciplinary.json |
Competitions that clearly span two or more categories, e.g. robotics |
{
"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": "your-github-handle",
"verified": { "by": "your-github-handle", "on": "2026-09-05" },
"valid_till": "2027-09-05"
}Fields:
id: kebab-case slug, unique across every file indata/competitions/. Base it on the competition's name, e.g.regeneron-isef,harvard-model-united-nations.category: must match the filename exactly.subjects: free-form tags, lowercase, e.g.["biology"]or["debate", "public speaking"].description: one to three plain sentences, written fresh by you. See Sourcing rules below, this is a hard requirement.format:online,in_person, orhybrid.age_min/age_max: the eligible age range. Use the organizer's own published range.participation:individual,team, orindividual_or_team.region:"international"if open worldwide with no single home country, otherwise the ISO-3166 alpha-2 code of the competition's home country (e.g."US","GB").fee: entry fee as{ "amount": number, "currency": "XXX" }. Use0if free to enter.official_url/organizer_url: the competition's own site and the organizing body's site. Often the same URL.cycle_year: the competition year thedatesbelow describe.dates: every date a student needs, each with:type: one ofregistration_open,registration_close,deadline,round,results,ceremony.timezone: the UTC offset the date/time was read in, e.g."UTC-4".estimated:trueif this date is a best guess following the typical cycle rather than a confirmed date for the current cycle. Be honest here, a wrong "confirmed" date is worse than an honest estimate.source_url: the exact page you read the date from. Must resolve - check it loads before you open a PR. Prefer the competition's own official site over a third-party catalog.
country_tracks: optional. Only add this when a real national qualifying pathway exists, for one ofIN US GB CA AU SG DE FR CN JP KR BR ZA. Do not fabricate a pathway that doesn't exist. Each stage needs its ownsource_urltoo.added_by: your GitHub username.verified/valid_till: see Verification below.
Take facts only: names, organizers, dates, fees, eligibility, age ranges, prizes, official URLs, and real country qualifying pathways. Facts are not copyrightable.
Write every description fresh. Do not copy prose from doq.world, Wikipedia, or any
other catalog or the competition's own marketing copy. One to three sentences, plain, no
marketing register ("prestigious", "world-class", and similar are out). A lift is visible
in git history forever on a public repo, and it isn't necessary, the facts are enough.
Do not import anyone else's prestige or selectivity rating. StudyMap does not make that editorial call.
Competitions can carry an optional verified block recording that a contributor
re-checked the record:
"verified": {
"by": "your-github-handle",
"on": "2026-08-14"
}byis the verifier's GitHub username;onis the ISO date (YYYY-MM-DD) they checked it.- A verification stays valid for 6 months. Dates and fees change fast enough, and a countdown timer showing a stale date is worse than showing none, so competitions default to a shorter window than places.
- After the window, the record should be re-verified (update
verified.onand any dates that changed) or theverifiedblock removed. valid_tillrecords the date the whole record should be reconfirmed by, independent of theverifiedblock above; the freshness cron uses it to flag records that need a look.npm run validatefails on a malformedverifiedblock (missing or emptyby, a non-date or impossibleon, or extra keys), on asource_urlthat doesn't look like a URL, and on any string field containing an em dash.
Include in your pull request description:
- Source or citation showing the competition is real
- Confirmation every
source_urlresolves (you opened each one) - Confirmation the
descriptionis your own writing, not copied from any source - Date you verified the fees, dates and eligibility
feat(data): add competition - Regeneron ISEF
One competition per commit is fine. Multiple competitions of the same category in one commit is also fine.
The list of valid categories lives in more than one place. Adding a category (e.g. a new
<category>.json) also requires:
src/lib/types.ts- extend the competition category union (labels/colors derive from it)data/competitions.schema.json- extend thecategoryenum.github/ISSUE_TEMPLATE/add-competition.yml- extend the dropdown