Writing
An article is standard Markdown plus a small set of written controls for metadata, visibility, and layout. Every control is an HTML comment, so a GMTales article is still a valid Markdown file that renders cleanly in any editor.
Standard Markdown Support
All the usual Markdown works: headings, emphasis, lists, links, images, inline code and code blocks, blockquotes, tables, and horizontal rules.
Titles
The first level-one heading (#) becomes the article's title, used for auto-linking, discovery, and display throughout the campaign. Every article needs one; directives may sit above it.
Titles don't have to be unique: GMTales disambiguates collisions, and a key gives an article a stable, unambiguous reference when you need one.
A comma in a title splits it into separately-matched names — # Ashford, Halden answers to "Ashford", "Halden" and "Halden Ashford" — so leave the comma out if you don't want the parts matched. See Linking.
Directives
Controls come in three forms:
Single-line:
<!-- key: value -->Flag:
<!-- pinned -->,<!-- main -->Block:
<!-- start: type -->…<!-- end: type -->
A block opens with start: or begin: (the two are interchangeable) and closes with end: naming the same type. The editor's autocomplete inserts start:.
Arguments
Everything that takes arguments takes them the same way. A declaration — a directive or a block header — separates its arguments with ;:
Every declaration has an ordered list of named parameters, listed in the reference below. Write arguments by position, in that order, or by name as name=value:
Positional arguments come first, and once you name one, you name the rest. In practice that means the main value by position and anything further by name:
Returning to position after a name is a validation error. Once a name has been given, position no longer says anything:
The remaining rules:
;separates arguments;,does not. A comma belongs to the argument it sits in: a group list, a coordinate pair, a date.48,30is one argument, and so isgm, party.An empty argument is a slip, not a blank. A stray trailing
;, aname=with nothing after it, and an empty entry in a comma-separated list (gm,, party) are all validation errors; leave the argument out instead.An entry repeated in a comma-separated list is a validation error too, and case does not make it a different entry:
alias: the Wood, The Woodnames the same alias twice, since matching ignores case.Only trailing optional arguments may be left out of the positional part. Writing more arguments than the declaration has parameters won't save, and a parameter can't be given twice, by position and then by name.
On/off arguments carry no value. Write
thumbnailto turn it on and leave it out to turn it off;thumbnail=trueis an error, because presence is the value. A bare on/off name counts as named, so<!-- start: image; thumbnail -->is the flag with no image. An image genuinely called "thumbnail" needssrc=thumbnail.An unknown name is a validation error, never a value.
speaker=Ostrenon a quote is an error, not an attribution.Free text is unaffected. Only
=introduces a name, so<!-- start: quote; Ostren: The Grey Chronicle -->is an attribution, colon and all. A positional value that genuinely needs aword=inside it goes in the block's body instead.
Argument Reference
Blocks
Block | Arguments, in order |
|---|---|
— | |
| |
| |
| |
| |
| |
| |
| |
|
Directives
Directive | Arguments, in order |
|---|---|
| one required value, named after the directive |
|
|
|
|
|
|
|
|
|
|
| |
| |
| |
|
|
|
|
marker is the only declaration with two lists. Outside an image block it has to name the image it pins to; inside one, the block already says which image that is.
A time directive written without a description dates the article itself, and an article has one time: one at, or one from and one to, across the whole document. A second bound of a kind already written is a validation error. See Chronology.
Controls Are Validated When You Save
GMTales never guesses at what you wrote. A control that could mean more than one thing, or that names something that doesn't exist, is a validation error: the save fails with a message naming the offending control, and the article stays as it was until the text is clean. Nothing is silently defaulted or dropped.
Mistake | Example |
|---|---|
Unknown directive name |
|
Unknown flag |
|
Unknown block type |
|
Unmatched block marker |
|
A block parameter it can't read |
|
Content a restricted block doesn't accept | a paragraph of prose inside a box |
A directive where it can't apply |
|
A block written where nothing reads it | a |
A secret nested inside another block | |
A stray comma in a list |
|
A repeated entry in a list |
|
A reference to something that isn't there |
|
An article with no | anything without a level-one heading, or a |
Because unrecognised names are validation errors, HTML comments are not quite free-form: a comment shaped <!-- name: value -->, such as <!-- TODO: rewrite this -->, or a single bare word, reads as a control and won't save under an unknown name. Keep scratch notes in a note or a private secret block.
The preview runs the same checks as the save, and it lists every problem it finds, so a document with three mistakes takes one round to fix. An unclosed or misspelled block marker is reported on its own, because nothing below it can be read until it is fixed. A few checks need the campaign's records — a key already in use, a tree parent that must exist, an event date that must parse in its calendar — and those are made by the save itself.
Recognised is not the same as allowed everywhere. An image's own content and the body of an image block each take a narrower set, and a directive that nothing reads there is a validation error.
One exception: a misspelled builtin: icon name cannot be checked at save time and simply shows no icon.
Drafts and Publishing
An article is finished when you say it is. The editor saves two different ways.
Save draft keeps your working copy. Nobody else can read it. Publish makes what is in the editor the article the campaign reads. Write across as many evenings as you like, saving a draft each time, and publish once at the end.
An asterisk on the button, Save draft *, means the editor holds changes you have not saved yet.
An article has one draft at a time. Saving a draft replaces the one before it, so there is no history of drafts to browse and no way back to an earlier one.
Two saves do less than they appear to. Saving a draft that says exactly what is already published throws the draft away, which is how you abandon a change: paste the published text back and save. Saving a draft identical to the draft already there writes nothing at all.
The Draft Banner
An article you have a draft on carries a banner at the top of the page, in the editor and on the article itself, with Publish and Discard draft beside it. Once the article has a published version, the banner's Compare shows it against your draft, with your unpublished changes marked as additions.
What Only You See
While a draft is open, everything you browse reads it. Your article list, search, automatic links and trees all show the draft's title, labels and text. Draft a dozen articles on the Siege Years and they link to each other in your own view before a word of it is public.
Everyone else reads the published version, and an article that has only ever been a draft is not in their list, their search, their feed or their links. They are not told a draft exists either: the badge, the banner and the count are yours alone.
In your own list, Draft marks an article with unpublished changes and Unpublished marks one that has never been published. Show drafts in the overview bar filters to just those, and appears only when you have one.
Discarding
Discard draft throws the working copy away and the article reads as its published version again. The published version is untouched.
What Publishing Does
Publishing is the moment the campaign hears about the article. It dates the article, puts it in the activity feed, marks it unread for the members who can read it, and rebuilds its links in both directions. Saving a draft does none of that, which is why a half-written article never announces itself.
Publishing also clears the draft. The published text becomes a revision and the draft is gone.
Publishing the same article from two tabs fails on the second rather than overwriting the first: GMTales says the article has been published again since you opened it, so open it afresh and make the change there. Both the published version and your draft survive.
A draft may give a key to an article that has none, but changing a key it already has is a validation error: a key is how the rest of the campaign refers to the article, not something a private working copy changes. Publish the change instead, or put the old key back.
Metadata Directives
Type
Files the article under one category, used by filters and type icons. A type is created the first time an article names it.
Labels
Free-form tags for filtering and search, comma-separated. Spaces around a comma are trimmed.
Labels belong to the passage that declares them, so a labels directive written inside a secret block is read only by that secret's audience. One directive per passage: a second labels in the same passage is a validation error.
Key
An identifier that stays stable when the title changes, unique within the campaign. Used for explicit links.
Aliases
Alternate names the article can be auto-linked by, comma-separated. Like labels, aliases belong to the passage that declares them, one directive per passage.
Relevance
A number for how central the article is. It drives the relevance sort and the relevance threshold filter in overviews. See Discovery.
Pinned
A pinned article sorts first in list view, whatever the sort order.
Main
Marks the article as the campaign's landing point, typically its introduction. One per campaign; removing the directive un-sets it. The Main tab shows it as an article page, with the same subpages and control panel as any other article.
Only the campaign's creator can set the main article; in someone else's campaign, main in an article of yours is a validation error. Removing it is always allowed, and un-sets the campaign's landing point only when it is already this article.
A draft carrying this directive does not move the landing point. It takes effect when you publish.
Portrait
Sets the article's portrait from an uploaded image, referenced by file name. The portrait appears beside the article in lists and on the article page.
Any image you can see will do. Every upload is stored at portrait size as well, so there is nothing to prepare and nothing to upload twice. Naming your own upload types it Portrait in the gallery; naming someone else's leaves their type alone.
An article has one portrait; a second portrait directive is a validation error.
Visibility Control
Article-Level Visibility
The visibility directive restricts the whole article. me means author-only, a group key (like party or gm) targets that group, and multiple targets are comma-separated. Without the directive, the article is open to the whole campaign.
Secret Blocks
A secret block hides one passage of an otherwise visible article:
Secrets covers how visibilities combine and what they carry with them.
Formatting Blocks
Blocks differ in how much Markdown they accept:
Block | Body content |
|---|---|
Any Markdown, including other blocks | |
Any Markdown, including other blocks | |
Any Markdown, including other blocks | |
Any Markdown (nested blocks are not processed) | |
Restricted — headings, | |
Restricted — list items or headings with paragraphs | |
Restricted — a caption, description, and image directives | |
Restricted — the pin's text, and no blocks | |
Restricted — the area's text, and no blocks |
Box
A styled fact panel, rendered as a two-column table. Its body accepts exactly three kinds of content, in any order and any number:
Content | Renders as |
|---|---|
A heading ( | A full-width title row spanning both columns |
A list item of the form | A row: the key on the left, the value on the right |
A paragraph containing an image | A full-width image row spanning both columns |
Anything else is a validation error.
The split is at the first colon in the item.
**Title**: Warden of Highcairn; later King at Highcairngives the keyTitleand keeps the rest, semicolons and all, as the value.A list item with no colon is a validation error ("Each list item must use the format: key: value").
Bullet lists (
*,-,+) and numbered lists both work and render identically; the bullets and numbers themselves are dropped.Inline Markdown works in both key and value: bold, italics, code, links, auto-links. Bolding the key is convention, not a requirement.
Headings group rows inside one panel. The heading level doesn't change the rendering.
Columns
Accepts any Markdown at all, flowed into responsive columns. Other GMTales blocks may be nested inside and render normally.
The count argument widens it. The default is 2:
The only counts are 2, 3 and 4; anything else is a validation error.
Timeline
A chronology. The body is written one of two ways; mixing them in one body puts the two entry styles side by side, so pick one.
Headings with paragraphs — the heading is the date, the paragraphs beneath it are the entry:
List items of the form date: entry, split at the first colon:
A paragraph before any heading is a validation error; there is no entry for it to belong to. So is a list item with no colon.
Entry bodies are full Markdown: bold, links, images and auto-links all work.
In the heading form the date is plain text: formatting in the heading is stripped rather than rendered, so write
## Fifth Era 3019, not## *Fifth Era 3019*. In the list form the date keeps its formatting.A
calendarargument binds the timeline to an in-world calendar. It is then a list syntax overtimementions: each entry is dated against that Calendar and joins the chronology, and the block is sorted and grouped by in-world date rather than by the order you wrote it. Without the argument, the timeline is a plain list in your own order.
Quote
A stylized pull-quote. The body accepts any Markdown; the optional argument is the attribution, rendered beneath the quote with an em dash.
With no attribution the quote renders without one; put the credit in the body if you'd rather style it yourself.
A secret block can't sit inside any other block; see Nesting.
Tree Relations
The tree directive places an article in a named tree, optionally under a parent:
The tree name is required; the parent is optional. The tree itself is created the first time an article names it. The parent is another article, named by title or by key, and it must already exist in the campaign; a title matching two articles is a validation error rather than a guess, so use a key when titles collide.
An article joins several trees with one tree directive each. Naming the same tree twice in one article is a validation error:
Cycles are not allowed. Trees are browsed in the tree view.
Image Blocks
An image block places an uploaded image and carries that image's record. Its src names the image, and the thumbnail flag makes it the article's thumbnail in overview lists:
The body is not article prose. Its first heading is the caption and its paragraphs are the image's description. It accepts the labels, parent and marker directives and the marker and region blocks, and all of them describe the image, not the article. Everything else about an image belongs to its own content and is a validation error here. Images spells out each part.
For a simple inline picture, standard Markdown still works. The alt text prints under the picture and is kept as this reference's description; the image itself gains no description of its own, no labels and no pins:
An image reference resolves by file name, then key, then title; directories in the path are ignored. See Image references.
Import and Export
The same Markdown works in the web editor and in any editor of your own. Export your articles as .md files, edit them locally with search-and-replace, refactoring, or git, and import them back; every directive travels with the file. Image references survive the round trip because they resolve by file name, so keep image file names unique and stable.
What comes back lands as drafts by default, so an upload is something you read through and publish rather than something that takes effect the moment it arrives. Files covers the mechanics and the review that follows.