一键导入
gum-docs-writing
Writing Gum docs in GitBook markdown. Triggers: editing docs/, SUMMARY.md, GitBook hints/figures, cross-page links, doc images.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Writing Gum docs in GitBook markdown. Triggers: editing docs/, SUMMARY.md, GitBook hints/figures, cross-page links, doc images.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Gum tool C# code generation. Triggers: CodeGenerator, CodeOutputPlugin, generated code structure, .codsj settings, OutputLibrary selection, Forms codegen, state generation. For CLI/headless codegen see gum-cli.
Where runtime-feature demo screens go. Triggers: adding a sample/demo page for a new runtime feature, NineSliceScreen/SpriteScreen, shape demos, MonoGameGumInCode, Samples/raylib, SilkNetGum.
Forms DefaultVisuals — code-only visual classes backing Forms controls. Triggers: ButtonVisual, any *Visual class in DefaultVisuals/, Styling, DefaultFormsTemplates registration, custom code-only Forms visuals.
Building or modifying a Gum theme package (Themes/Gum.Themes.*) — restyling Forms controls by subclassing their V3 default visuals. Triggers: any file under Themes/, custom *Visual subclassing Gum.Forms.DefaultVisuals.V3.*, theme entry-point methods like EditorTheme.Apply / DarkProTheme.Apply.
Test-first discipline for Gum. Triggers: behavior changes (bug fix or feature) under GumCommon/, Gum/, MonoGameGum/, RenderingLibrary/, KniGum/, FnaGum/, SkiaGum/, RaylibGum/, Tools/Gum.ProjectServices/. Skip for docs, renames, csproj/projitems plumbing, style-only edits.
Unifying per-platform runtime files (MonoGame/Raylib/Skia/KNI/FNA, plus the Apos.Shapes ↔ SkiaGum shape-runtime pair) into one source with
| name | gum-docs-writing |
| description | Writing Gum docs in GitBook markdown. Triggers: editing docs/, SUMMARY.md, GitBook hints/figures, cross-page links, doc images. |
All docs live under docs/. docs/SUMMARY.md is the master table of contents — GitBook navigation is built entirely from it. A file not listed in SUMMARY.md is unreachable from the nav even if it exists on disk.
Every new file must be added to SUMMARY.md with a 2-space indent per nesting level:
* [Section](gum-tool/section/README.md)
* [Page Title](gum-tool/section/page.md)
* [Sub-page](gum-tool/section/sub/page.md)
Paths in SUMMARY.md are relative to docs/.
A README.md inside a folder is the section's landing page. In SUMMARY.md, link it as folder/README.md. Sub-pages of that section are indented under it.
All images live in docs/.gitbook/assets/. Reference them using a depth-relative path from the page file:
docs/gum-tool/gum-elements/general-properties/x-units.md → ../../../.gitbook/assets/filename.pngdocs/gum-tool/gum-elements/skia-standard-elements/arc/README.md → ../../../../.gitbook/assets/filename.pngImage filename convention: date-time prefix like 15_06 10 06.png (day_hour minute second) or 08_14 21 31.gif. Spaces in filenames require wrapping the path in <> angle brackets in standard Markdown image syntax: . In <figure> tags the src attribute handles spaces without angle brackets.
Some images use a generic image (N).png naming pattern with numeric suffixes like image (13) (1).png — these are GitBook-uploaded files; don't rename them.
Hint blocks — must always have a closing {% endhint %} tag or the page breaks:
{% hint style="info" %}
Content here.
{% endhint %}
{% hint style="warning" %}
Content here.
{% endhint %}
Figure blocks — used for images with captions. Always include alt attribute and <figcaption>:
<figure><img src="../../../.gitbook/assets/filename.png" alt=""><figcaption><p>Caption text</p></figcaption></figure>
For inline images without captions, use standard Markdown: .
HTML entities —   (space) and d (d) appear in GitBook-generated content for spacing and special characters. Do not strip them; GitBook uses them intentionally.
Always use relative paths — no absolute URLs. Link to a section landing page using its README.md:
[Container](../container/README.md)
Do not use anchor-only links to other files (e.g., [foo](other-file.md#section) is fine, but [foo](#section) only works within the same page).
The docs have two top-level sections — Gum Tool (docs/gum-tool/) and Code (docs/code/). These must never be mixed:
gum-tool/) describe the Gum UI tool — properties, editors, menus, and workflows within the tool. They should not contain C# code samples or reference runtime APIs.docs/code/) describe using Gum at runtime in game code — C# APIs, Forms controls, layout in code, etc. They should not describe how to use the Gum tool UI.When writing a tool doc page (e.g., a property page under gum-elements/), focus entirely on the tool experience: what the property does visually, where it appears in the UI, and screenshots showing the effect. Do not add code examples showing how to set the property in C#. Conversely, code doc pages should not walk through the tool's UI.
Some features cut across many controls — binding, localization, theming, code generation — and individual controls have control-specific behaviors that intersect with them. For example, TextBox.Text can be bound to a numeric ViewModel property and the binding implicitly converts string ↔ number; ListBox interacts with BindingContext differently than other controls; localized labels behave differently in PasswordBox.
The convention for these:
docs/code/binding-viewmodels/, localization rules in the localization section, etc. This is the single source of truth.[Implicit Type Conversion](../binding-viewmodels/advanced-binding-options.md#implicit-type-conversion)). Do not duplicate the system-level explanation — trust the reader to follow the link.The control-page note exists so that a reader troubleshooting "why doesn't my int binding take" while reading the TextBox page finds what they need without bouncing around. The feature-page section exists so that a reader learning the binding system isn't surprised later. Both audiences are real; the split avoids both blind spots without duplicating content.
Anything that is only true relative to a release date — "as of ", "before ", "in X changed" — must live in a {% hint %} block, not in the body paragraphs of a section. Phrase the surrounding prose in terms of current behavior so it stays correct after the dated note is removed.
Why: dated notes eventually become noise once enough time has passed (everyone reading the docs is on the new behavior). Keeping them in hint blocks gives a single, visually obvious anchor to delete later instead of forcing the author to re-read every paragraph hunting for embedded dates.
Pattern:
The Font Generator project property controls ... There are two options:
* **KernSmith** — ... This is the default for new projects.
* **BMFont** — ... a separate external tool.
{% hint style="info" %}
**As of May 2026:** New projects default to **KernSmith**. Before this, the default was **BMFont**. Existing projects keep their current setting.
{% endhint %}
Not this — date leaks into body bullets, so removing the dated context later means rewriting prose:
* **KernSmith** — ... Default for new projects starting in May 2026.
* **BMFont** — ... Was the default before May 2026.
This applies to: "as of ", "starting in ", "before ", "in version X", "the May 2026 release", and any "what changed in " section heading. When in doubt: if deleting the sentence later would leave the surrounding paragraph still accurate, it's safe in the body; if deleting it would leave a contradiction or dangling reference, lift it into a hint.
Width Units, Relative To Children, Is Tiling Middle Sections..png) for single states; animated GIFs (.gif) for multi-step interactions. Use them liberally.Every \``csharp` block must have a placement comment as its first line so readers and agents know where the code belongs.
| Comment | Meaning |
|---|---|
// Initialize | General initialization — could be Initialize(), CustomInitialize(), a constructor, etc. Use this by default. |
// Update | Code that runs each frame in the update loop. |
// Draw | Code that runs each frame in the draw loop. |
// Class scope | Field or property declarations at class level. |
// In CustomInitialize | Code specifically in a generated partial CustomInitialize() method. |
When to omit the comment:
using statements — self-evident, no comment needed.Mixed-scope snippets (class members + method bodies): use // Class scope for the member declarations, then show the actual method block(s) with full signatures and indented bodies — no outer class wrapper:
// Class scope
int clickCount;
protected override void Initialize()
{
var button = new Button();
button.Click += (_, _) => clickCount++;
}
Platform-agnostic by default: prefer // Initialize over MonoGame-specific phrasing unless the page is explicitly MonoGame-only. This supports Raylib and other runtimes.
Irreducible per-platform syntax → tabs, don't ask. First try to collapse a sample to a single platform-neutral form. When the syntax genuinely cannot collapse — most often because a member's type differs per backend (e.g. KeyCombo.PushedKey / KeyEventArgs.Key is XNA Microsoft.Xna.Framework.Input.Keys on MonoGame but Gum.Forms.Input.Keys on Raylib, same names/values but distinct types; or a host skeleton that's a Game subclass vs a Program.Main loop) — wrap just those blocks in GitBook {% tabs %} with one {% tab %} per platform (e.g. MonoGame / Raylib). This is the standard, expected treatment for irreducible divergence; use it without asking. Keep the surrounding prose shared above/below the tabs — only the code that truly differs goes inside.
For adding or updating XnaFiddle interactive links, see xnafiddle.md.
GumUI.UseKeyboardDefaults(), GumUI.UseGamepadDefaults(), input-device registration, service configuration) at the top of the sample, right under the // Initialize comment where GumUI is set up — before the feature code. Readers copy a sample as one block, so a setup call buried between feature lines reads as part of the feature logic and is confusing. Group setup first, then the feature it enables. Bad: create the control, add items, then UseKeyboardDefaults(), then wire focus. Good: UseKeyboardDefaults() first, then create the control and wire focus.GetType(), typeof(), MemberInfo, or any System.Reflection APIs in doc code samples. Use is pattern matching instead: if (device is Gum.Input.Keyboard).System.DateTime not DateTime. Do not rely on implicit using statements for non-Gum types.Label instead of writing it to the output window. Avoid System.Console.WriteLine (requires opening the diagnostics window) and System.Diagnostics.Debug.WriteLine (breaks in NetFiddle) on any page intended to be fiddle-able. The one exception is a page whose subject is debugging — where the sample's output is a developer-facing diagnostic that nobody will fiddle (e.g. the events troubleshooting page). There, a breakpoint-and-inspect or Debug.WriteLine is the natural tool and is acceptable; visible-label output would be contrived.{% endhint %} closing tag breaks all content after it on the page.<figure> tags without alt and <figcaption> may not render correctly in GitBook.<figcaption> content must be wrapped in <p> tags: <figcaption><p>Caption</p></figcaption>.csharp language identifier: ```csharp.# Title (H1) at the top. Sections within a page use ## and ### — avoid jumping heading levels.<!-- TODO -->) for placeholders because they are invisible in the rendered docs. Instead use a warning hint block so the placeholder is obvious when browsing the docs.