Lewati ke konten utama

Writing an editorial

How to add an editorial or a material: file locations, frontmatter fields, MDX and math, and where the visualization goes.

Terakhir diperbarui 11 Oktober 2026

Halaman ini belum diterjemahkan ke bahasa Indonesia. Halaman yang ditampilkan dalam bahasa Inggris.

Editorials and materials are plain MDX files committed to the repository. Content has no database. Files under content/ are compiled at build time.

Where files go

  • Editorials: content/editorials/<subject>/<slug>.mdx
  • Materials: content/materials/<subject>/<slug>.mdx

<subject> is informatics, physics or astronomy. The URL's slug comes from the filename and not the title, so renaming a title never changes a published URL.

Editorial frontmatter

FieldNotes
titleUp to 120 characters.
subjectMust match the folder the file is in.
hookUp to 280 characters. One sentence that makes someone want to read on.
tagsShort, lowercase labels.
principleThe general idea this editorial teaches. Free text on purpose.
errorTypeOptional. The specific mistake it corrects. Free text.
vizConfigWhich visualization engine to use, and its configuration.
publishedAtAn ISO date, 2020 or later. Earlier dates are rejected as placeholder data.
updatedAtOptional ISO date for the last editorial or visualization update. Falls back to publishedAt when omitted.
statuspublished (the default) or draft. Draft editorials are visible to editors only and hidden from everyone else.
authorWho wrote it.
syllabusTopicOptional. A topic id, or a subtopic id, from the syllabus for the same subject.
practiceLinksOptional. A list of { title, url, checkedOn } for practice problems on other sites (for example TLX). url must be https://. See below.

The body is everything after the frontmatter, written in Markdown/MDX.

Math

Use $...$ for inline math and $$...$$ for display math. Both compile to static KaTeX HTML at build time.

Placing the visualization

Put <Interactive /> on its own line where the visualization should appear, usually between the idea and the full proof. If you forget it, the visualization still renders, just after the hook with a small notice, so an editorial never ships without one.

Hiding the solution until the reader asks

Wrap a worked solution or proof in <Solution> on its own lines, with a blank line after the opening tag and before the closing tag:

<Solution>

## Full proof

...

</Solution>

By default everyone sees the full text. A reader can switch on "Try it first" (saved only in their browser), and then solutions collapse behind a "Show solution" control. Every <Solution> must be closed, and pnpm test checks that.

Use practiceLinks to point at problems that belong to someone else. Link only: do not copy a problem statement. Set checkedOn to the day you last opened the link. After 180 days the page marks the link as possibly moved, so re-check it and update the date.

Choosing a visualization engine

Set vizConfig.discriminant to one of graph-array-stepper, trajectory-sandbox, orbital-sandbox, blackbody-spectrum-comparison, relative-period-sandbox, composed-scene or programmable-scene. The first five are configured in frontmatter. The last two are built visually in the scene builder. Copy from these real examples:

  • content/editorials/informatics/binary-search-on-answer.mdx for graph-array-stepper
  • content/editorials/physics/projectile-range-symmetry.mdx for trajectory-sandbox
  • content/editorials/astronomy/eccentric-transit-duration.mdx for orbital-sandbox
  • content/editorials/astronomy/why-classical-blackbody-radiation-fails.mdx for blackbody-spectrum-comparison
  • content/editorials/astronomy/why-a-sidereal-day-is-shorter.mdx for relative-period-sandbox

Adding a challenge to a trajectory sandbox

A trajectory-sandbox can pose a problem instead of only offering sliders. Add an optional challenge next to speedRange and angleRange in vizConfig.value:

challenge:
  prompt: "Land the ball on the marker. Use $R = v^2 \\sin 2\\theta / g$ to plan your launch."
  target: { rangeM: 60, toleranceM: 2 }
  hint: "Two different angles reach the same range."
  successNote: "That is the symmetry behind this editorial."

prompt, hint and successNote are Markdown with $...$ math. The reader sets a launch, presses Play, and when the flight ends the page checks that the landing is within toleranceM of rangeM. After two misses the hint appears. Attempts are counted in the reader's browser only.

The page refuses to build a challenge that cannot be won. rangeM and toleranceM must be positive numbers, and some setting the sliders can actually produce (in whole steps of 1 m/s and 1°, within speedRange and angleRange, or the defaults of 5 to 40 m/s and 5° to 85°) must land inside the tolerance. If it cannot, the visualization shows a configuration error. Check a new target with pnpm test, or open the page.

Keystatic does not know about challenge yet, so an editorial that has one cannot be opened in the Keystatic form (the same limit as a programmable scene). Edit it in the file.

Materials

A material is shorter and unsigned. It has a title, subject, topic (a syllabus topic id or subtopic id), summary (up to 280 characters) and a body. There is at most one material per topic or subtopic. A visualization is optional: set vizConfig the same way as for an editorial (the first three engines; the scene builder only writes editorials) and place <Interactive /> where it belongs. With discriminant: none, or no vizConfig at all, a material simply has no visualization. See content/materials/informatics/binary-search.mdx for an example.

Checking your work

Run pnpm generate to validate frontmatter and pnpm test to check that every material and editorial points at a real syllabus topic. Never rename a syllabus topic's or subtopic's id. Change its name instead.

Languages

An editorial or material is written in one language, set by the optional language field (en by default). To translate it, add a file next to it named <slug>.id.mdx (or .en.mdx) holding only the translated title, hook (summary for a material) and body. Readers in that language get the translation; everyone else sees the original with a notice. You never switch the notice off by hand: it appears only while the translation is missing.

Editing in the browser

You can also write and edit content in the browser. See Editing with Keystatic.