Create a ROJ Contest
SkillDocs & knowledgeCreate or update ROJ contest Markdown records under this repository's contests/ directory from user-provided contest information or a local contest source. Use when the user asks to create, add, register, or prepare a contest page for web2. Do not use this skill to import individual problems into roj/; use add-roj-problem instead.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Create a ROJ Contest skill
What this skill tells your AI
The instructions your AI receives, as published by rainboyoj/problems in .agents/skills/add-roj-contest/SKILL.md and read by ahel’s review.
Create a reviewable contest record for the read-only ROJ website. The deliverable is a
top-level contests/<slug>.md file and, when needed, an adjacent
contests/<slug>/ resource directory. This is content preparation for the existing
Fastify + Pug site, not an online-judge, registration, submission, or scoring feature.
When this skill applies
Use it when the user asks to create or maintain a contest page, contest announcement,
contest schedule, or contest overview for this repository, including requests based on
a local contest directory such as /home/rainboy/tmp-暑假比赛.
Do not use it for these unrelated tasks:
- Importing a problem, assigning a
roj/<id>, copyingdata/,down/, orstd.cpp: useadd-roj-problem. - Changing web2 routes, templates, styling, or the contest data model: treat that as an application implementation task and inspect the web2 code directly.
- Publishing files to GitHub, deploying to the VPS, or committing changes: leave those actions to the user unless they explicitly request them.
Read the repository contract first
Before writing anything, inspect the current implementation and working tree:
- Read
web2/README.mdfor the current contest-file contract. - Read
web2/server/contest-catalog.mjsand the contest Pug views when they exist. - Inspect
contests/for existing slugs and resource directories. - Inspect
roj/only to verify problem IDs that the contest will link to. Do not recursively scan unrelated paths or infer a missing problem import from this task. - Preserve unrelated user changes in the worktree.
The implementation is the source of truth if the instructions below and the code have drifted. Report a contract mismatch before writing when it would change the resulting URLs or file format.
Contest file contract
Only Markdown files directly under contests/ are discovered. A file's basename is its
URL slug:
contests/2026-summer.md -> /contest/2026-summer
Use a unique lowercase slug containing only ASCII letters, digits, _, and -.
Prefer a stable event/date slug such as 2026-summer or 2026-08-training; do not
silently transliterate an ambiguous Chinese title. If the appropriate slug is unclear,
ask the user. Never overwrite an existing contests/<slug>.md without explicit
permission; a collision is a stop-and-ask condition.
The required frontmatter is title. Supported fields are:
---
title: 2026 暑假训练赛
date: 2026-07-01
endDate: 2026-07-07
description: 暑假期间的训练赛
organizer: ROJ
status: upcoming
tags: [训练赛, 暑假]
draft: false
---
Field rules:
titleis a non-empty human-readable string. Do not use the slug as a substitute unless the user explicitly wants that title.dateis the start date andendDateis the inclusive end date. Use ISOYYYY-MM-DD; reject impossible dates and do not invent missing dates.statusis optional and, when present, must beupcoming,ongoing, orarchived. If omitted, the site infers it from the dates using theAsia/Shanghaicalendar.description,organizer, andtagsare optional. Keep tags as a list of strings.draft: truehides the contest from both the list and detail routes. Use it for an intentionally unpublished page, not as a way to conceal an unresolved error.- Unknown frontmatter fields are allowed by the current site and are displayed as extra metadata. Preserve meaningful source fields, but do not copy credentials, local absolute paths, private URLs, or implementation-only noise.
If a date or status is not known, omit it rather than guessing. If the source contains times, time zones, or date ranges that cannot be represented by these fields, preserve the detail in the Markdown body and call out the limitation in the preview.
Source discovery and problem mapping
The user may provide a complete Markdown draft, a local contest root, or only structured details. Classify the input before editing:
- For a Markdown draft, parse its frontmatter and body; preserve useful content while normalizing links and unsupported raw HTML.
- For a local contest root, inspect only its immediate files and clearly named overview material first. Identify the contest title, dates, organizer, schedule, problem labels, and explanatory text. Do not treat every child directory as a problem import.
- For a request with no source and no usable contest details, ask for the missing title, slug, or source instead of fabricating a contest.
Problem links in the contest body must use standard Markdown links to existing ROJ pages:
- [A. 两数之和](/problem/1000)
- [B. 统计](/problem/1001)
The site extracts /problem/<number> links from the rendered body, deduplicates them
in first-appearance order, and displays a generated “比赛题目” section. Before the
preview, verify every proposed ID exists as a usable entry under roj/ (Markdown or
PDF-only). If a source problem has not been imported yet, do not allocate an ID or
create a partial contest link: tell the user to import it with add-roj-problem, or
ask for the correct existing ID. A missing ID may remain in the body only if the user
explicitly wants a placeholder; mark it as unresolved and explain that it will not
appear in the generated list.
Keep external links as ordinary Markdown links. The renderer opens HTTP(S) links in a new window. Do not turn local absolute paths into links.
Images and resources
Use the optional adjacent directory for contest images:
contests/
2026-summer.md
2026-summer/
schedule.png
venue.jpg
With the current renderer, a local image in contests/<slug>/ is referenced from the
Markdown using the slug prefix:

Only existing image files with .png, .jpg, .jpeg, .gif, .webp, or .svg
extensions are served through /contest/<slug>/asset/.... Keep paths relative, use
forward slashes, and never use .., backslashes, or absolute filesystem paths. The
site does not expose arbitrary contest attachments, source code, test data, or a
general download directory through this feature.
If a local image is missing, report it in the preview and either fix the source path or leave a clearly marked missing-image warning after the user chooses to proceed. Do not copy unrelated files merely because they are next to the source Markdown.
Normalize the Markdown
The web2 renderer supports headings, paragraphs, lists, tables, fenced code, links, images, LaTeX, and the repository's existing Markdown containers. Keep the contest page focused on information a reader needs: overview, schedule, rules/notes, problem list, and references.
Do not copy raw HTML that the renderer will drop. When the source is HTML or contains
structural HTML, use pandoc or another appropriate parser to convert it to standard
Markdown, then inspect headings, lists, tables, formulas, code blocks, links, and image
paths. Do not replace a structured conversion with a broad regular-expression rewrite.
Do not duplicate the generated “比赛题目” section in the body solely for the site. The body should contain the canonical links and surrounding explanation; the page creates the compact list automatically.
Review-first workflow
Do not write the final contest file immediately. Follow this sequence:
- Build a manifest containing the proposed slug, title, dates, status, organizer, tags, source path, body sections, problem-link mappings, image paths, and warnings.
- Check slug collisions, frontmatter validity, date validity, problem existence, local image existence, and whether the source contains unsupported or private material.
- Present a flat preview with the exact destination path, frontmatter, proposed problem links, resource files, and every unresolved choice. State whether the page is draft or public.
- Wait for explicit confirmation of the complete preview. A vague “looks fine” about only one field is not confirmation for the whole write.
- Create the Markdown and resource directory only after confirmation. Write through a temporary directory when transforming a larger source, then move into place without replacing an existing destination.
For an existing contest that the user explicitly asks to update, show a before/after preview and preserve fields and body sections not covered by the request. If the update would change the slug or replace existing resources, ask separately before making that destructive change.
Validate after writing
Verify all of the following before reporting success:
contests/<slug>.mdexists at the exact requested path and parses withgray-matter.titleis present and non-empty; dates are valid ISO dates; status and tags follow the contract;drafthas the intended value.- The Markdown body contains the intended problem links, and each non-placeholder ID
exists in
roj/. - Every local image reference resolves within
contests/<slug>/and uses an allowed image extension; no path escapes the resource directory. - No raw structural HTML, credentials, local absolute paths, or accidental private source material was copied.
- The slug appears at most once, and no unrelated file was overwritten.
git diff --checkis clean for the new or changed text files.- If the web2 server is running, request
/contestsand/contest/<slug>and confirm the page title, status, generated problem list, and images render as expected. A missing problem must remain a logged warning and must not make the page fail.
Do not claim that the page is publicly deployed or that a link is available on GitHub until the user commits/pushes the files and deploys the repository. Leave Git commands and VPS operations to the user.
Minimal template
Use this as a starting point, adapting it to the actual contest information:
---
title: 2026 暑假训练赛
date: 2026-07-01
endDate: 2026-07-07
description: 暑假期间的训练赛
organizer: ROJ
tags: [训练赛]
---
## 比赛说明
这里写比赛背景、适用对象和注意事项。
## 时间安排
- 比赛时间:2026-07-01 至 2026-07-07
## 题目
- [A. 两数之和](/problem/1000)
Signals
- GitHub stars
- 34
- Forks
- 20
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
add-roj-contest- Source
- github.com/rainboyoj/problems