Skip to main content

Portable Markdown publication contract

View Markdown versionEdit this page on GitHub

This page defines the portable Markdown publication contract used for LongitudeOne documentation. The goal is to ensure that every published document is predictable, independently consumable, machine-friendly, and semantically similar to its HTML representation.

This contract is intentionally strict. It prevents Docusaurus-specific details from leaking into the published Markdown and it guarantees that Markdown output remains usable outside the Docusaurus rendering environment.

Scope​

The portable publication format is GitHub Flavored Markdown (GFM).

Published Markdown must not depend on any of the following:

  • MDX;
  • JSX;
  • React components;
  • Docusaurus-specific rendering constructs;
  • raw embedded HTML.

If a source element cannot be represented in the portable Markdown contract without losing relevant semantic meaning, the build must fail instead of silently skipping or degrading the content.

Publication identity and path rules​

Every published documentation resource must have two explicit representations:

  • an HTML representation using the .html extension;
  • a Markdown representation using the .md extension.

The publication contract does not use directory-style document identities or implicit index.html resolution.

HTML and Markdown counterparts are published in the same directory and differ only by their representation extension. An internal staging or generation directory must not introduce a public markdown/ prefix. For example, /shared/index.html is paired with /shared/index.md, not /markdown/shared/index.md. This rule also applies to llms.txt, resource mappings, download links and deployed files, including development base URLs.

For example:

Source:
docs/spatial-core/geometry/point.md

HTML:
/spatial-core/geometry/point.html

Markdown:
/spatial-core/geometry/point.md

The following representation is not valid:

/spatial-core/geometry/point/

The explicit representation is:

/spatial-core/geometry/point.html

Path components used for published documentation must follow strict portable naming rules:

  • lowercase characters only;
  • no spaces;
  • no problematic or reserved path characters;
  • suitability for case-sensitive filesystems and URLs.

This rule applies to both the source hierarchy and the generated HTML/Markdown representations. For example, the following names are valid:

docs/spatial-core/geometry/point.md

The following are invalid:

docs/Spatial-Core/geometry/point.md
docs/spatial-core/Geometry/Point.md
docs/spatial-core/geometry/point example.md

Documentation paths are treated as case-sensitive on every supported platform. The file names point.md and Point.md must never be considered equivalent, including on case-insensitive local filesystems.

Production resource negotiation​

In production, the extensionless URI (for example, /shared/index) identifies an abstract documentation resource. Apache internally selects the existing .html or .md representation from the HTTP Accept header, without a redirect. This virtual endpoint is not a third representation or a source-document link target.

Explicit .html and .md URLs always select their representation, regardless of Accept. Existing source and generated link rules continue to require explicit representation extensions, including the representation switching links.

Negotiation respects media ranges and quality values. HTML wins equal preferences and is the default for absent Accept or */*. A quality of zero rejects that representation; a request accepting neither representation receives HTTP 406. Negotiated responses expose Vary: Accept and the selected text/html or text/markdown content type. Both representation files must exist.

The production corpus includes the version-controlled, deterministically generated .htaccess infrastructure. Apache MultiViews is disabled; only the paired HTML and Markdown files are eligible. Physical files and directories bypass negotiation. GitHub Pages and the local static preview do not implement this server behavior.

Localized document identities​

A language suffix is part of the resource name. For example, legal-notice.fr.md maps to legal-notice.fr.html; legal-notice.en.md maps to legal-notice.en.html. The negotiated production resource endpoints are legal-notice.fr and legal-notice.en. The .fr.md suffix identifies French HTML content; unsuffixed and .en.md sources use English. Language switches remain ordinary relative .md links in source and portable Markdown, and become explicit .html links in the HTML representation.

Required metadata​

Every published Markdown document must contain YAML front matter. The metadata must include at least the following fields:

---
title: Point
description: Represents a zero-dimensional geometry.
---

The title and description values are mandatory. Docusaurus-specific metadata must not appear in the publication output unless it has independent semantic value for the published document.

Examples of metadata that must not be propagated solely because Docusaurus uses them include sidebar ordering and rendering configuration. The source slug field is not supported: publication paths are derived from the source hierarchy. The generated front matter contains only title, description, canonical_html, and canonical_markdown.

Deterministic generation​

The Markdown representation is generated from the source document using a Markdown syntax tree, not by rewriting source text with regular expressions. Generation must be deterministic and idempotent: identical source documents must produce byte-identical output, and rerunning generation without source changes must not modify the published corpus.

Generated Markdown must use UTF-8 without a byte-order mark and LF line endings. HTML comments in source are removed; other raw HTML and content that cannot be represented without semantic loss must cause generation to fail. index.md documents retain an explicit index.html representation. Generated files are staged and promoted as one publication operation so a failed generation does not replace the last valid corpus.

Representation URLs​

The publication process must generate two canonical representation URLs for each document:

  • the canonical HTML URL;
  • the canonical Markdown URL.

These values are derived automatically from the source document path and must not require manual duplication in each source file.

The HTML representation URL must always use the .html extension. The Markdown representation URL must always use the .md extension.

For example:

---
title: Point
description: Represents a zero-dimensional geometry.
canonical_html: ./point.html
canonical_markdown: ./point.md
---

An index.md source must map to:

canonical_html: ./index.html
canonical_markdown: ./index.md

The exact metadata field names and serialization may vary across implementations, but the publication contract must clearly distinguish both representations.

Document titles and headings​

The document title is defined by the mandatory title metadata. The publication generator must not insert an additional level-one Markdown heading solely to repeat this title.

Therefore, this is not required:

# Point

when the document already declares the title in YAML front matter.

The first content heading may therefore begin at level two.

Every published Markdown document must provide an explicit link to its HTML representation immediately after the document metadata and therefore directly below the title when a consumer renders the metadata.

For example:

[View HTML version](./point.html)

This link must:

  • use a relative path;
  • explicitly include the .html extension;
  • point directly to the matching HTML representation.

Directory-style URLs such as the following are not valid:

[View HTML version](./point/)

Links between documents in the same published documentation corpus must remain inside the Markdown representation.

For example:

[LineString](./linestring.md)

must be used instead of:

[LineString](./linestring.html)
[LineString](./linestring/)
[LineString](https://example.org/docs/linestring.html)

Internal documentation links must:

  • use relative paths;
  • explicitly include the .md extension;
  • target the published Markdown representation;
  • preserve document fragments when present;
  • respect the exact lowercase path of the target document.

Absolute URLs are forbidden for links whose destination belongs to the same published documentation corpus.

Validation resolves AST link nodes against the published source hierarchy under docs/, before canonical serialization or replacement of the published corpus. Directory targets and extensionless links are source errors; the generator never adds .md, infers index.md, repairs casing or falls back to HTML. Documentation targets cannot escape docs/ or use symbolic links. A target must be an included, real source document; drafts, unlisted and hidden pages cannot be linked as published documentation.

Inline and reference-style links follow the same rules. Their paths are canonicalized relative to the source document; external URLs, query strings, fragments, code and literal text retain their meaning. Shared asset references are distinguished from documentation links and are not rewritten by this step. An outside relative resource requires an existing shared static publication resource; arbitrary files outside docs/ are not documentation targets.

Errors identify the source path, original and resolved target, reason, and line and column when available. Invalid links fail generation before publication, leaving the previous generated corpus intact.

The explicit View HTML version link remains the intentional exception that allows navigation from Markdown to the corresponding HTML representation.

Every published Markdown page must be reachable from index.md by following these internal Markdown links. The resource verifier checks this coverage after generation; listing a page only in llms.txt or an HTML sidebar is insufficient for a reader browsing the Markdown corpus.

Heading anchors​

Links to document sections may use GFM-compatible generated heading anchors.

For example:

[Coordinate dimension](./point.md#coordinate-dimension)

Generated anchor values must be predictable according to the chosen GFM rules. Internal fragment links must be validated during the documentation build. A link targeting a nonexistent generated anchor must fail validation.

Same-document links remain fragment-only links. Cross-document fragments must resolve against the target's GFM headings. Heading-anchor collisions are errors, including headings with different formatting that produce the same anchor. Authors must use distinct headings rather than relying on automatically generated numeric suffixes to distinguish repeated headings.

Shared assets​

Resources shared between HTML and Markdown representations must not be duplicated. Published Markdown should reference shared assets using paths relative to the current Markdown document.

For example:

![Geometry hierarchy](../../assets/images/geometry-hierarchy.svg)

Root-relative references such as the following are not allowed in the portable Markdown representation when a relative reference can be generated:

![Geometry hierarchy](/assets/images/geometry-hierarchy.svg)

This rule applies to all shared resources, including:

  • images;
  • diagrams;
  • schemas;
  • downloadable files;
  • example data files;
  • externally stored code samples;
  • other static documentation assets.

The resulting Markdown corpus remains navigable when moved together with its shared asset hierarchy.

The shared assets publication contract defines the dedicated source hierarchy, allowed formats, safety validation, manifest and atomic publication requirements.

Raw HTML and unsupported content​

Raw HTML must not be part of the portable Markdown publication format. Content requiring HTML must be rewritten using supported Markdown constructs.

The generator must not silently preserve unsupported HTML as a fallback. If equivalent semantic content cannot be produced using the supported Markdown profile, the build must fail.

This includes any case where a source construct:

  • has no supported portable Markdown representation;
  • would lose relevant semantic information during conversion;
  • cannot be converted deterministically.

Warnings alone are insufficient when a semantic conversion failure occurs.

Admonitions​

Admonitions must be represented using portable Markdown constructs rather than Docusaurus-specific directives. A simple blockquote representation is used.

For example:

> **Warning**
>
> This geometry representation is not supported.

A standardized set of labels such as Note, Warning, Important, and Tip may be used when it improves clarity. The representation must remain legible in a generic Markdown renderer that provides no special admonition support.

Tables​

GFM tables are part of the publication format.

| Dimension | Coordinates |
|-----------|-------------|
| XY | X, Y |
| XYZ | X, Y, Z |

Tables must remain valid GFM and must not depend on HTML table markup. Columns must be aligned. If a construct cannot reasonably be represented as a GFM table, it must be expressed using another portable Markdown structure.

Code blocks​

Fenced code blocks must declare a language identifier whenever the content language or format is known.

For example:

```php
$geometry = new Point(...);
```

A known language must not be emitted as an untyped fenced block. Domain-specific identifiers may be used when they add useful semantics, including:

  • php;
  • json;
  • sql;
  • wkt;
  • ewkt;
  • geojson;
  • other clearly identified formats used by LongitudeOne documentation.

Build-only comments and directives​

Comments, annotations, and directives used exclusively by the documentation build process must be removed from the published Markdown representation. They must not be exposed merely because they appear in the source file.

Information intended for documentation consumers must instead be represented as document content or publication metadata.

Table of contents​

The publication generator must not inject a table of contents into individual Markdown documents. Document headings remain available to consumers who wish to derive their own navigation.

This avoids duplicating structure that is already expressed by the document's headings.

Semantic equivalence​

HTML and Markdown are different representations of the same documentation resource. They are not required to produce identical visual presentation or identical markup structure.

They must, however, convey the same normative and technical information.

The governing rule is:

The HTML and Markdown representations must convey the same normative and technical information, while presentation may differ according to the capabilities of each format.

A difference in presentation is acceptable. A difference that removes, changes, or ambiguously transforms technical or normative meaning is not acceptable.

Summary of required constraints​

The portable Markdown publication contract requires the following:

  • GitHub Flavored Markdown is the publication format.
  • Markdown output must not require MDX, JSX, React, or Docusaurus-specific rendering behavior.
  • Raw HTML is forbidden in portable Markdown.
  • Each published resource has explicit .html and .md representations.
  • Directory-style HTML identities are forbidden.
  • index.md maps explicitly to index.html and index.md.
  • Documentation file and directory names use lowercase characters only.
  • Spaces and problematic path characters are rejected.
  • Paths are treated as case-sensitive on every platform.
  • Every published document contains YAML front matter.
  • title and description are mandatory.
  • Representation URLs are generated automatically from source paths.
  • The HTML link is present immediately after metadata as a relative link to the corresponding .html resource.
  • Internal links target the .md representation with relative paths.
  • GFM anchors are supported and validated.
  • Shared assets use relative paths.
  • Admonitions, tables, and fenced code blocks use portable Markdown patterns.
  • Build-only comments and directives are removed from published output.
  • The generator does not inject a table of contents.
  • Semantic conversion failures cause the build to fail.

This contract is the reference for implementation, generation, linting, and CI validation in the following stories.